diff --git a/configure.in b/configure.in index 7e05fb41f738..2cd8e3e7deb8 100644 --- a/configure.in +++ b/configure.in @@ -4144,6 +4144,8 @@ MOZ_CUBEB= MOZ_VORBIS= MOZ_TREMOR= MOZ_WAVE=1 +MOZ_SAMPLE_TYPE_FLOAT32= +MOZ_SAMPLE_TYPE_S16LE= MOZ_MEDIA= MOZ_OPUS=1 MOZ_WEBM=1 @@ -5192,6 +5194,19 @@ fi AC_SUBST(MOZ_WEBRTC) +case "$target_cpu" in +arm*) + MOZ_SAMPLE_TYPE_S16LE=1 + AC_DEFINE(MOZ_SAMPLE_TYPE_S16LE) + AC_SUBST(MOZ_SAMPLE_TYPE_S16LE) +;; +*) + MOZ_SAMPLE_TYPE_FLOAT32=1 + AC_DEFINE(MOZ_SAMPLE_TYPE_FLOAT32) + AC_SUBST(MOZ_SAMPLE_TYPE_FLOAT32) +;; +esac + dnl ======================================================== dnl = Enable Raw Codecs dnl ======================================================== @@ -5220,14 +5235,6 @@ if test -n "$MOZ_OGG"; then MOZ_SYDNEYAUDIO=1 MOZ_CUBEB=1 MOZ_MEDIA=1 - case "$target_cpu" in - arm*) - MOZ_TREMOR=1 - ;; - *) - MOZ_VORBIS=1 - ;; - esac dnl Checks for __attribute__(aligned()) directive AC_CACHE_CHECK([__attribute__ ((aligned ())) support], @@ -5367,14 +5374,11 @@ if test "$MOZ_WEBM"; then MOZ_SYDNEYAUDIO=1 MOZ_CUBEB=1 MOZ_MEDIA=1 - case "$target_cpu" in - arm*) - MOZ_TREMOR=1 - ;; - *) + if test "$MOZ_SAMPLE_TYPE_FLOAT32"; then MOZ_VORBIS=1 - ;; - esac + else + MOZ_TREMOR=1 + fi fi if test -n "$MOZ_VP8" -a -z "$MOZ_NATIVE_LIBVPX"; then diff --git a/content/html/content/src/nsHTMLAudioElement.cpp b/content/html/content/src/nsHTMLAudioElement.cpp index 50fdf27bd6ac..b33b9cf2767c 100644 --- a/content/html/content/src/nsHTMLAudioElement.cpp +++ b/content/html/content/src/nsHTMLAudioElement.cpp @@ -116,8 +116,7 @@ nsHTMLAudioElement::MozSetup(PRUint32 aChannels, PRUint32 aRate) } mAudioStream = nsAudioStream::AllocateStream(); - nsresult rv = mAudioStream->Init(aChannels, aRate, - nsAudioStream::FORMAT_FLOAT32); + nsresult rv = mAudioStream->Init(aChannels, aRate); if (NS_FAILED(rv)) { mAudioStream->Shutdown(); mAudioStream = nullptr; @@ -169,7 +168,30 @@ nsHTMLAudioElement::MozWriteAudio(const JS::Value& aData, JSContext* aCx, PRUint // Don't write more than can be written without blocking. PRUint32 writeLen = NS_MIN(mAudioStream->Available(), dataLength / mChannels); - nsresult rv = mAudioStream->Write(JS_GetFloat32ArrayData(tsrc, aCx), writeLen); + float* frames = JS_GetFloat32ArrayData(tsrc, aCx); +#ifdef MOZ_SAMPLE_TYPE_S16LE + // Convert the samples back to integers as we are using fixed point audio in + // the nsAudioStream. + nsAutoArrayPtr shortsArray(new short[writeLen * mChannels]); + // Hard clip the samples. + for (PRUint32 i = 0; i < writeLen * mChannels; ++i) { + float scaled_value = floorf(0.5 + 32768 * frames[i]); + if (frames[i] < 0.0) { + shortsArray[i] = (scaled_value < -32768.0) ? + -32768 : + short(scaled_value); + } else { + shortsArray[i] = (scaled_value > 32767.0) ? + 32767 : + short(scaled_value); + } + } + nsresult rv = mAudioStream->Write(shortsArray, writeLen); +#else + nsresult rv = mAudioStream->Write(frames, writeLen); +#endif + + if (NS_FAILED(rv)) { return rv; } diff --git a/content/media/MediaStreamGraph.cpp b/content/media/MediaStreamGraph.cpp index 4d104f63ac87..2e56073202da 100644 --- a/content/media/MediaStreamGraph.cpp +++ b/content/media/MediaStreamGraph.cpp @@ -1150,8 +1150,7 @@ MediaStreamGraphImpl::CreateOrDestroyAudioStreams(GraphTime aAudioOutputStartTim audioOutputStream->mBlockedAudioTime = 0; audioOutputStream->mStream = nsAudioStream::AllocateStream(); audioOutputStream->mStream->Init(audio->GetChannels(), - tracks->GetRate(), - audio->GetFirstFrameFormat()); + tracks->GetRate()); audioOutputStream->mTrackID = tracks->GetID(); } } diff --git a/content/media/nsAudioStream.cpp b/content/media/nsAudioStream.cpp index 5502d615a9dc..9ce4d0fffff0 100644 --- a/content/media/nsAudioStream.cpp +++ b/content/media/nsAudioStream.cpp @@ -60,7 +60,7 @@ class nsNativeAudioStream : public nsAudioStream ~nsNativeAudioStream(); nsNativeAudioStream(); - nsresult Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat); + nsresult Init(PRInt32 aNumChannels, PRInt32 aRate); void Shutdown(); nsresult Write(const void* aBuf, PRUint32 aFrames); PRUint32 Available(); @@ -95,7 +95,7 @@ class nsRemotedAudioStream : public nsAudioStream nsRemotedAudioStream(); ~nsRemotedAudioStream(); - nsresult Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat); + nsresult Init(PRInt32 aNumChannels, PRInt32 aRate); void Shutdown(); nsresult Write(const void* aBuf, PRUint32 aFrames); PRUint32 Available(); @@ -422,11 +422,11 @@ nsNativeAudioStream::~nsNativeAudioStream() NS_IMPL_THREADSAFE_ISUPPORTS0(nsNativeAudioStream) -nsresult nsNativeAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat) +nsresult nsNativeAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate) { mRate = aRate; mChannels = aNumChannels; - mFormat = aFormat; + mFormat = MOZ_AUDIO_DATA_FORMAT; if (sa_stream_create_pcm(reinterpret_cast(&mAudioHandle), NULL, @@ -474,53 +474,40 @@ nsresult nsNativeAudioStream::Write(const void* aBuf, PRUint32 aFrames) if (s_data) { double scaled_volume = GetVolumeScale() * mVolume; - switch (mFormat) { - case FORMAT_U8: { - const PRUint8* buf = static_cast(aBuf); - PRInt32 volume = PRInt32((1 << 16) * scaled_volume); - for (PRUint32 i = 0; i < samples; ++i) { - s_data[i] = short(((PRInt32(buf[i]) - 128) * volume) >> 8); - } - break; - } - case FORMAT_S16_LE: { - const short* buf = static_cast(aBuf); - PRInt32 volume = PRInt32((1 << 16) * scaled_volume); - for (PRUint32 i = 0; i < samples; ++i) { - short s = buf[i]; +#ifdef MOZ_SAMPLE_TYPE_S16LE + const short* buf = static_cast(aBuf); + PRInt32 volume = PRInt32((1 << 16) * scaled_volume); + for (PRUint32 i = 0; i < samples; ++i) { + short s = buf[i]; #if defined(IS_BIG_ENDIAN) - s = ((s & 0x00ff) << 8) | ((s & 0xff00) >> 8); + s = ((s & 0x00ff) << 8) | ((s & 0xff00) >> 8); #endif - s_data[i] = short((PRInt32(s) * volume) >> 16); - } - break; - } - case FORMAT_FLOAT32: { - const float* buf = static_cast(aBuf); - for (PRUint32 i = 0; i < samples; ++i) { - float scaled_value = floorf(0.5 + 32768 * buf[i] * scaled_volume); - if (buf[i] < 0.0) { - s_data[i] = (scaled_value < -32768.0) ? - -32768 : - short(scaled_value); - } else { - s_data[i] = (scaled_value > 32767.0) ? - 32767 : - short(scaled_value); - } - } - break; + s_data[i] = short((PRInt32(s) * volume) >> 16); + } +#else /* MOZ_SAMPLE_TYPE_FLOAT32 */ + const SampleType* buf = static_cast(aBuf); + for (PRUint32 i = 0; i < samples; ++i) { + float scaled_value = floorf(0.5 + 32768 * buf[i] * scaled_volume); + if (buf[i] < 0.0) { + s_data[i] = (scaled_value < -32768.0) ? + -32768 : + short(scaled_value); + } else { + s_data[i] = (scaled_value > 32767.0) ? + 32767 : + short(scaled_value); } } +#endif + } - if (sa_stream_write(static_cast(mAudioHandle), - s_data.get(), - samples * sizeof(short)) != SA_SUCCESS) - { - PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsNativeAudioStream: sa_stream_write error")); - mInError = true; - return NS_ERROR_FAILURE; - } + if (sa_stream_write(static_cast(mAudioHandle), + s_data.get(), + samples * sizeof(short)) != SA_SUCCESS) + { + PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsNativeAudioStream: sa_stream_write error")); + mInError = true; + return NS_ERROR_FAILURE; } return NS_OK; } @@ -644,26 +631,12 @@ NS_IMPL_THREADSAFE_ISUPPORTS0(nsRemotedAudioStream) nsresult nsRemotedAudioStream::Init(PRInt32 aNumChannels, - PRInt32 aRate, - SampleFormat aFormat) + PRInt32 aRate) { mRate = aRate; mChannels = aNumChannels; - mFormat = aFormat; - - switch (mFormat) { - case FORMAT_U8: { - mBytesPerFrame = sizeof(PRUint8) * mChannels; - break; - } - case FORMAT_S16_LE: { - mBytesPerFrame = sizeof(short) * mChannels; - break; - } - case FORMAT_FLOAT32: { - mBytesPerFrame = sizeof(float) * mChannels; - } - } + mFormat = MOZ_AUDIO_DATA_FORMAT; + mBytesPerFrame = sizeof(SampleType) * mChannels; nsCOMPtr event = new AudioInitEvent(this); NS_DispatchToMainThread(event, NS_DISPATCH_SYNC); @@ -861,7 +834,7 @@ class nsBufferedAudioStream : public nsAudioStream nsBufferedAudioStream(); ~nsBufferedAudioStream(); - nsresult Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat); + nsresult Init(PRInt32 aNumChannels, PRInt32 aRate); void Shutdown(); nsresult Write(const void* aBuf, PRUint32 aFrames); PRUint32 Available(); @@ -963,7 +936,7 @@ nsBufferedAudioStream::~nsBufferedAudioStream() NS_IMPL_THREADSAFE_ISUPPORTS0(nsBufferedAudioStream) nsresult -nsBufferedAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat) +nsBufferedAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate) { cubeb* cubebContext = GetCubebContext(); @@ -973,23 +946,17 @@ nsBufferedAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aF mRate = aRate; mChannels = aNumChannels; - mFormat = aFormat; + mFormat = MOZ_AUDIO_DATA_FORMAT; cubeb_stream_params params; params.rate = aRate; params.channels = aNumChannels; - switch (aFormat) { - case FORMAT_S16_LE: - params.format = CUBEB_SAMPLE_S16LE; - mBytesPerFrame = sizeof(short) * aNumChannels; - break; - case FORMAT_FLOAT32: - params.format = CUBEB_SAMPLE_FLOAT32NE; - mBytesPerFrame = sizeof(float) * aNumChannels; - break; - default: - return NS_ERROR_FAILURE; - } +#ifdef MOZ_SAMPLE_TYPE_S16LE + params.format = CUBEB_SAMPLE_S16NE; +#else /* MOZ_SAMPLE_TYPE_FLOAT32 */ + params.format = CUBEB_SAMPLE_FLOAT32NE; +#endif + mBytesPerFrame = sizeof(float) * aNumChannels; { cubeb_stream* stream; @@ -1221,30 +1188,22 @@ nsBufferedAudioStream::DataCallback(void* aBuffer, long aFrames) output += input_size[i]; } else { // Adjust volume as each sample is copied out. - switch (mFormat) { - case FORMAT_S16_LE: { - PRInt32 volume = PRInt32(1 << 16) * scaled_volume; +#ifdef MOZ_SAMPLE_TYPE_S16LE + PRInt32 volume = PRInt32(1 << 16) * scaled_volume; - const short* src = static_cast(input[i]); - short* dst = reinterpret_cast(output); - for (PRUint32 j = 0; j < input_size[i] / (mBytesPerFrame / mChannels); ++j) { - dst[j] = short((PRInt32(src[j]) * volume) >> 16); - } - output += input_size[i]; - break; + const short* src = static_cast(input[i]); + short* dst = reinterpret_cast(output); + for (PRUint32 j = 0; j < input_size[i] / (mBytesPerFrame / mChannels); ++j) { + dst[j] = short((PRInt32(src[j]) * volume) >> 16); } - case FORMAT_FLOAT32: { - const float* src = static_cast(input[i]); - float* dst = reinterpret_cast(output); - for (PRUint32 j = 0; j < input_size[i] / (mBytesPerFrame / mChannels); ++j) { - dst[j] = src[j] * scaled_volume; - } - output += input_size[i]; - break; - } - default: - return -1; +#else /* MOZ_SAMPLE_TYPE_FLOAT32 */ + const float* src = static_cast(input[i]); + float* dst = reinterpret_cast(output); + for (PRUint32 j = 0; j < input_size[i] / (mBytesPerFrame / mChannels); ++j) { + dst[j] = src[j] * scaled_volume; } +#endif + output += input_size[i]; } } diff --git a/content/media/nsAudioStream.h b/content/media/nsAudioStream.h index b1d63fc8bb7e..24e127348987 100644 --- a/content/media/nsAudioStream.h +++ b/content/media/nsAudioStream.h @@ -11,6 +11,14 @@ #include "nsIThread.h" #include "nsAutoPtr.h" +#ifdef MOZ_SAMPLE_TYPE_S16LE +#define MOZ_AUDIO_DATA_FORMAT (nsAudioStream::FORMAT_S16_LE) +typedef short SampleType; +#else +#define MOZ_AUDIO_DATA_FORMAT (nsAudioStream::FORMAT_FLOAT32) +typedef float SampleType; +#endif + // Access to a single instance of this class must be synchronized by // callers, or made from a single thread. One exception is that access to // GetPosition, GetPositionInFrames, SetVolume, and Get{Rate,Channels,Format} @@ -28,8 +36,7 @@ public: nsAudioStream() : mRate(0), - mChannels(0), - mFormat(FORMAT_S16_LE) + mChannels(0) {} virtual ~nsAudioStream(); @@ -56,7 +63,7 @@ public: // (22050Hz, 44100Hz, etc). // Unsafe to call with a monitor held due to synchronous event execution // on the main thread, which may attempt to acquire any held monitor. - virtual nsresult Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat) = 0; + virtual nsresult Init(PRInt32 aNumChannels, PRInt32 aRate) = 0; // Closes the stream. All future use of the stream is an error. // Unsafe to call with a monitor held due to synchronous event execution @@ -106,7 +113,7 @@ public: int GetRate() { return mRate; } int GetChannels() { return mChannels; } - SampleFormat GetFormat() { return mFormat; } + SampleFormat GetFormat() { return MOZ_AUDIO_DATA_FORMAT; } protected: nsCOMPtr mAudioPlaybackThread; diff --git a/content/media/nsBuiltinDecoderReader.h b/content/media/nsBuiltinDecoderReader.h index ae75c7b4507f..9e9928ed6116 100644 --- a/content/media/nsBuiltinDecoderReader.h +++ b/content/media/nsBuiltinDecoderReader.h @@ -53,29 +53,25 @@ public: bool mHasVideo; }; -#ifdef MOZ_TREMOR +#ifdef MOZ_SAMPLE_TYPE_S16LE #include typedef ogg_int32_t VorbisPCMValue; typedef short AudioDataValue; -#define MOZ_AUDIO_DATA_FORMAT (nsAudioStream::FORMAT_S16_LE) #define MOZ_CLIP_TO_15(x) ((x)<-32768?-32768:(x)<=32767?(x):32767) // Convert the output of vorbis_synthesis_pcmout to a AudioDataValue #define MOZ_CONVERT_VORBIS_SAMPLE(x) \ (static_cast(MOZ_CLIP_TO_15((x)>>9))) // Convert a AudioDataValue to a float for the Audio API #define MOZ_CONVERT_AUDIO_SAMPLE(x) ((x)*(1.F/32768)) -#define MOZ_SAMPLE_TYPE_S16LE 1 -#else /*MOZ_VORBIS*/ +#else /* MOZ_SAMPLE_TYPE_FLOAT32 */ typedef float VorbisPCMValue; typedef float AudioDataValue; -#define MOZ_AUDIO_DATA_FORMAT (nsAudioStream::FORMAT_FLOAT32) #define MOZ_CONVERT_VORBIS_SAMPLE(x) (x) #define MOZ_CONVERT_AUDIO_SAMPLE(x) (x) -#define MOZ_SAMPLE_TYPE_FLOAT32 1 #endif diff --git a/content/media/nsBuiltinDecoderStateMachine.cpp b/content/media/nsBuiltinDecoderStateMachine.cpp index 9592abf41f9a..86e591a7f501 100644 --- a/content/media/nsBuiltinDecoderStateMachine.cpp +++ b/content/media/nsBuiltinDecoderStateMachine.cpp @@ -1008,7 +1008,7 @@ void nsBuiltinDecoderStateMachine::AudioLoop() // are unsafe to call with the decoder monitor held are documented as such // in nsAudioStream.h. nsRefPtr audioStream = nsAudioStream::AllocateStream(); - audioStream->Init(channels, rate, MOZ_AUDIO_DATA_FORMAT); + audioStream->Init(channels, rate); { // We must hold the monitor while setting mAudioStream or whenever we query diff --git a/dom/ipc/AudioParent.cpp b/dom/ipc/AudioParent.cpp index ce10c45d1a7a..386ee79c35df 100644 --- a/dom/ipc/AudioParent.cpp +++ b/dom/ipc/AudioParent.cpp @@ -297,9 +297,7 @@ AudioParent::AudioParent(PRInt32 aNumChannels, PRInt32 aRate, PRInt32 aFormat) { mStream = nsAudioStream::AllocateStream(); NS_ASSERTION(mStream, "AudioStream allocation failed."); - if (NS_FAILED(mStream->Init(aNumChannels, - aRate, - (nsAudioStream::SampleFormat) aFormat))) { + if (NS_FAILED(mStream->Init(aNumChannels, aRate))) { NS_WARNING("AudioStream initialization failed."); mStream = nullptr; return;