Exemplo n.º 1
0
void
AudioBuffer::MixToMono(JSContext* aJSContext)
{
  if (mJSChannels.Length() == 1) {
    // The buffer is already mono
    return;
  }

  // Prepare the input channels
  nsAutoTArray<const void*, GUESS_AUDIO_CHANNELS> channels;
  channels.SetLength(mJSChannels.Length());
  for (uint32_t i = 0; i < mJSChannels.Length(); ++i) {
    channels[i] = JS_GetFloat32ArrayData(mJSChannels[i]);
  }

  // Prepare the output channels
  float* downmixBuffer = new float[mLength];

  // Perform the down-mix
  AudioChannelsDownMix(channels, &downmixBuffer, 1, mLength);

  // Truncate the shared channels and copy the downmixed data over
  mJSChannels.SetLength(1);
  SetRawChannelContents(aJSContext, 0, downmixBuffer);
  delete[] downmixBuffer;
}
Exemplo n.º 2
0
void
AudioBuffer::CopyToChannel(JSContext* aJSContext, const Float32Array& aSource,
                           uint32_t aChannelNumber, uint32_t aStartInChannel,
                           ErrorResult& aRv)
{
  uint32_t length = aSource.Length();
  if (aChannelNumber >= NumberOfChannels() ||
      aStartInChannel + length >= mLength) {
    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
    return;
  }

  if (!mSharedChannels && JS_GetTypedArrayLength(mJSChannels[aChannelNumber]) != mLength) {
    // The array was probably neutered
    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
    return;
  }

  if (!RestoreJSChannelData(aJSContext)) {
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    return;
  }

  PodCopy(JS_GetFloat32ArrayData(mJSChannels[aChannelNumber]) + aStartInChannel,
          aSource.Data(), length);
}
Exemplo n.º 3
0
void
AudioBuffer::SetRawChannelContents(uint32_t aChannel, float* aContents)
{
  MOZ_ASSERT(!GetWrapperPreserveColor() && !mSharedChannels,
             "The AudioBuffer object should not have been handed to JS or have C++ callers neuter its typed array");
  PodCopy(JS_GetFloat32ArrayData(mJSChannels[aChannel]), aContents, mLength);
}
Exemplo n.º 4
0
void
AudioBuffer::CopyToChannel(JSContext* aJSContext, const Float32Array& aSource,
                           uint32_t aChannelNumber, uint32_t aStartInChannel,
                           ErrorResult& aRv)
{
  aSource.ComputeLengthAndData();

  uint32_t length = aSource.Length();
  CheckedInt<uint32_t> end = aStartInChannel;
  end += length;
  if (aChannelNumber >= NumberOfChannels() ||
      !end.isValid() || end.value() > mLength) {
    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
    return;
  }

  if (!mSharedChannels && JS_GetTypedArrayLength(mJSChannels[aChannelNumber]) != mLength) {
    // The array was probably neutered
    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
    return;
  }

  if (!RestoreJSChannelData(aJSContext)) {
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    return;
  }

  PodMove(JS_GetFloat32ArrayData(mJSChannels[aChannelNumber]) + aStartInChannel,
          aSource.Data(), length);
}
Exemplo n.º 5
0
bool
AudioBuffer::RestoreJSChannelData(JSContext* aJSContext)
{
  for (uint32_t i = 0; i < mJSChannels.Length(); ++i) {
    if (mJSChannels[i]) {
      // Already have data in JS array.
      continue;
    }

    // The following code first zeroes the array and then copies our data
    // into it. We could avoid this with additional JS APIs to construct
    // an array (or ArrayBuffer) containing initial data.
    JS::Rooted<JSObject*> array(aJSContext,
                                JS_NewFloat32Array(aJSContext, mLength));
    if (!array) {
      return false;
    }
    if (mSharedChannels) {
      // "4. Attach ArrayBuffers containing copies of the data to the
      // AudioBuffer, to be returned by the next call to getChannelData."
      const float* data = mSharedChannels->GetData(i);
      JS::AutoCheckCannotGC nogc;
      bool isShared;
      mozilla::PodCopy(JS_GetFloat32ArrayData(array, &isShared, nogc), data, mLength);
      MOZ_ASSERT(!isShared); // Was created as unshared above
    }
    mJSChannels[i] = array;
  }

  mSharedChannels = nullptr;

  return true;
}
Exemplo n.º 6
0
/* [implicit_jscontext] void writeToContext2D (in nsIDOMCanvasRenderingContext2D ctx, in jsval source, in long width, in long height); */
NS_IMETHODIMP dpoCContext::WriteToContext2D(nsIDOMCanvasRenderingContext2D *ctx, const JS::Value & source, PRInt32 width, PRInt32 height, JSContext* cx)
{
#ifdef DIRECT_WRITE
	JSObject *srcArray;
	nsresult result;

	result = ExtractArray(source, &srcArray, cx);
	if (NS_FAILED(result)) {
		return result;
	}

	uint32_t size = JS_GetTypedArrayLength(srcArray);

	if (size != width*height*4)
		return NS_ERROR_INVALID_ARG;

    if (JS_IsFloat32Array(srcArray)) {
		unsigned char *data = (unsigned char *) nsMemory::Alloc(size);
		float *src = JS_GetFloat32ArrayData(srcArray);
		for (int i = 0; i < size; i++) {
			float val = src[i];
			data[i] = val > 0 ? (val < 255 ? ((int) val) : 255) : 0;
		}
		ctx->PutImageData_explicit(0, 0, width, height, data, size, false, 0, 0, 0, 0);
        nsMemory::Free(data);
	} else if (JS_IsFloat64Array(srcArray)) {
		unsigned char *data = (unsigned char *) nsMemory::Alloc(size);
		double *src = JS_GetFloat64ArrayData(srcArray);
		for (int i = 0; i < size; i++) {
			double val = src[i];
			data[i] = val > 0 ? (val < 255 ? ((int) val) : 255) : 0;
		}
		ctx->PutImageData_explicit(0, 0, width, height, data, size, false, 0, 0, 0, 0);
        nsMemory::Free(data);
	} else if(JS_IsUint8ClampedArray(srcArray)) {
		uint8_t *src = JS_GetUint8ClampedArrayData(srcArray);
		ctx->PutImageData_explicit(0, 0, width, height, src, size, false, 0, 0, 0, 0);
	} else if(JS_IsUint8Array(srcArray)) {
		return NS_ERROR_INVALID_ARG;
	} else {
		return NS_ERROR_NOT_IMPLEMENTED;
	}

	return NS_OK;
#else /* DIRECT_WRITE */
	return NS_ERROR_NOT_IMPLEMENTED;
#endif /* DIRECT_WRITE */
}
Exemplo n.º 7
0
void
AudioBuffer::CopyFromChannel(const Float32Array& aDestination, uint32_t aChannelNumber,
                             uint32_t aStartInChannel, ErrorResult& aRv)
{
  aDestination.ComputeLengthAndData();

  uint32_t length = aDestination.Length();
  CheckedInt<uint32_t> end = aStartInChannel;
  end += length;
  if (aChannelNumber >= NumberOfChannels() ||
      !end.isValid() || end.value() > Length()) {
    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
    return;
  }

  JS::AutoCheckCannotGC nogc;
  JSObject* channelArray = mJSChannels[aChannelNumber];
  if (channelArray) {
    if (JS_GetTypedArrayLength(channelArray) != Length()) {
      // The array's buffer was detached.
      aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
      return;
    }

    bool isShared = false;
    const float* sourceData =
      JS_GetFloat32ArrayData(channelArray, &isShared, nogc);
    // The sourceData arrays should all have originated in
    // RestoreJSChannelData, where they are created unshared.
    MOZ_ASSERT(!isShared);
    PodMove(aDestination.Data(), sourceData + aStartInChannel, length);
    return;
  }

  if (!mSharedChannels.IsNull()) {
    CopyChannelDataToFloat(mSharedChannels, aChannelNumber, aStartInChannel,
                           aDestination.Data(), length);
    return;
  }

  PodZero(aDestination.Data(), length);
}
Exemplo n.º 8
0
void
AudioBuffer::CopyToChannel(JSContext* aJSContext, const Float32Array& aSource,
                           uint32_t aChannelNumber, uint32_t aStartInChannel,
                           ErrorResult& aRv)
{
  aSource.ComputeLengthAndData();

  uint32_t length = aSource.Length();
  CheckedInt<uint32_t> end = aStartInChannel;
  end += length;
  if (aChannelNumber >= NumberOfChannels() ||
      !end.isValid() || end.value() > mLength) {
    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
    return;
  }

  if (!RestoreJSChannelData(aJSContext)) {
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    return;
  }

  JS::AutoCheckCannotGC nogc;
  JSObject* channelArray = mJSChannels[aChannelNumber];
  if (JS_GetTypedArrayLength(channelArray) != mLength) {
    // The array's buffer was detached.
    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
    return;
  }

  bool isShared = false;
  float* channelData = JS_GetFloat32ArrayData(channelArray, &isShared, nogc);
  // The channelData arrays should all have originated in
  // RestoreJSChannelData, where they are created unshared.
  MOZ_ASSERT(!isShared);
  PodMove(channelData + aStartInChannel, aSource.Data(), length);
}
Exemplo n.º 9
0
void
AudioBuffer::SetRawChannelContents(JSContext* aJSContext, uint32_t aChannel,
                                   float* aContents)
{
  PodCopy(JS_GetFloat32ArrayData(mJSChannels[aChannel]), aContents, mLength);
}
Exemplo n.º 10
0
JSBool JSB_jsval_typedarray_to_dataptr( JSContext *cx, jsval vp, GLsizei *count, void **data, JSArrayBufferViewType t)
{
    JSObject *jsobj;
    JSBool ok = JS_ValueToObject( cx, vp, &jsobj );
    JSB_PRECONDITION2( ok && jsobj, cx, JS_FALSE, "Error converting value to object");

    // WebGL supports TypedArray and sequences for some of its APIs. So when converting a TypedArray, we should
    // also check for a possible non-Typed Array JS object, like a JS Array.

    if( JS_IsTypedArrayObject( jsobj ) ) {

        *count = JS_GetTypedArrayLength(jsobj);
        JSArrayBufferViewType type = JS_GetArrayBufferViewType(jsobj);
        JSB_PRECONDITION2(t==type, cx, JS_FALSE, "TypedArray type different than expected type");

        switch (t) {
        case js::ArrayBufferView::TYPE_INT8:
        case js::ArrayBufferView::TYPE_UINT8:
            *data = JS_GetUint8ArrayData(jsobj);
            break;

        case js::ArrayBufferView::TYPE_INT16:
        case js::ArrayBufferView::TYPE_UINT16:
            *data = JS_GetUint16ArrayData(jsobj);
            break;

        case js::ArrayBufferView::TYPE_INT32:
        case js::ArrayBufferView::TYPE_UINT32:
            *data = JS_GetUint32ArrayData(jsobj);
            break;

        case js::ArrayBufferView::TYPE_FLOAT32:
            *data = JS_GetFloat32ArrayData(jsobj);
            break;

        default:
            JSB_PRECONDITION2(false, cx, JS_FALSE, "Unsupported typedarray type");
            break;
        }
    } else if( JS_IsArrayObject(cx, jsobj)) {
        // Slow... avoid it. Use TypedArray instead, but the spec says that it can receive
        // Sequence<> as well.
        uint32_t length;
        JS_GetArrayLength(cx, jsobj, &length);

        for( uint32_t i=0; i<length; i++ ) {

            jsval valarg;
            JS_GetElement(cx, jsobj, i, &valarg);

            switch(t) {
            case js::ArrayBufferView::TYPE_INT32:
            case js::ArrayBufferView::TYPE_UINT32:
            {
                uint32_t e = JSVAL_TO_INT(valarg);
                ((uint32_t*)data)[i] = e;
                break;
            }
            case js::ArrayBufferView::TYPE_FLOAT32:
            {
                double e = JSVAL_TO_DOUBLE(valarg);
                ((GLfloat*)data)[i] = (GLfloat)e;
                break;
            }
            default:
                JSB_PRECONDITION2(false, cx, JS_FALSE, "Unsupported typedarray type");
                break;
            }
        }

    } else
        JSB_PRECONDITION2(false, cx, JS_FALSE, "Object shall be a TypedArray or Sequence");

    return JS_TRUE;
}