| @@ -434,16 +434,21 @@ void AudioDataConverters::convertFormatToFloat (DataFormat sourceFormat, const v | |||
| //============================================================================== | |||
| void AudioDataConverters::interleaveSamples (const float** source, float* dest, int numSamples, int numChannels) | |||
| { | |||
| AudioData::interleaveSamples<AudioData::Float32, AudioData::NativeEndian, | |||
| AudioData::Float32, AudioData::NativeEndian> (source, numChannels, dest, numChannels, numSamples); | |||
| using Format = AudioData::Format<AudioData::Float32, AudioData::NativeEndian>; | |||
| AudioData::interleaveSamples (AudioData::NonInterleavedSource<Format> { source, numChannels }, | |||
| AudioData::InterleavedDest<Format> { dest, numChannels }, | |||
| numSamples); | |||
| } | |||
| void AudioDataConverters::deinterleaveSamples (const float* source, float** dest, int numSamples, int numChannels) | |||
| { | |||
| AudioData::deinterleaveSamples<AudioData::Float32, AudioData::NativeEndian, | |||
| AudioData::Float32, AudioData::NativeEndian> (source, numChannels, dest, numChannels, numSamples); | |||
| } | |||
| using Format = AudioData::Format<AudioData::Float32, AudioData::NativeEndian>; | |||
| AudioData::deinterleaveSamples (AudioData::InterleavedSource<Format> { source, numChannels }, | |||
| AudioData::NonInterleavedDest<Format> { dest, numChannels }, | |||
| numSamples); | |||
| } | |||
| //============================================================================== | |||
| //============================================================================== | |||
| @@ -574,6 +579,8 @@ public: | |||
| beginTest ("Round-trip conversion: Float32"); | |||
| Test1 <AudioData::Float32>::test (*this, r); | |||
| using Format = AudioData::Format<AudioData::Float32, AudioData::NativeEndian>; | |||
| beginTest ("Interleaving"); | |||
| { | |||
| constexpr auto numChannels = 4; | |||
| @@ -586,10 +593,9 @@ public: | |||
| for (int i = 0; i < numSamples; ++i) | |||
| sourceBuffer.setSample (ch, i, r.nextFloat()); | |||
| AudioData::interleaveSamples<AudioData::Float32, AudioData::NativeEndian, | |||
| AudioData::Float32, AudioData::NativeEndian> (sourceBuffer.getArrayOfReadPointers(), numChannels, | |||
| destBuffer.getWritePointer (0), numChannels, | |||
| numSamples); | |||
| AudioData::interleaveSamples (AudioData::NonInterleavedSource<Format> { sourceBuffer.getArrayOfReadPointers(), numChannels }, | |||
| AudioData::InterleavedDest<Format> { destBuffer.getWritePointer (0), numChannels }, | |||
| numSamples); | |||
| for (int ch = 0; ch < numChannels; ++ch) | |||
| for (int i = 0; i < numSamples; ++i) | |||
| @@ -608,10 +614,9 @@ public: | |||
| for (int i = 0; i < numSamples; ++i) | |||
| sourceBuffer.setSample (0, ch + (i * numChannels), r.nextFloat()); | |||
| AudioData::deinterleaveSamples<AudioData::Float32, AudioData::NativeEndian, | |||
| AudioData::Float32, AudioData::NativeEndian> (sourceBuffer.getReadPointer (0), numChannels, | |||
| destBuffer.getArrayOfWritePointers(), numChannels, | |||
| numSamples); | |||
| AudioData::deinterleaveSamples (AudioData::InterleavedSource<Format> { sourceBuffer.getReadPointer (0), numChannels }, | |||
| AudioData::NonInterleavedDest<Format> { destBuffer.getArrayOfWritePointers(), numChannels }, | |||
| numSamples); | |||
| for (int ch = 0; ch < numChannels; ++ch) | |||
| for (int i = 0; i < numSamples; ++i) | |||
| @@ -326,6 +326,9 @@ public: | |||
| JNIEnv* env = getEnv(); | |||
| jshortArray audioBuffer = env->NewShortArray (actualBufferSize * jmax (numDeviceOutputChannels, numDeviceInputChannels)); | |||
| using NativeInt16 = AudioData::Format<AudioData::Int16, AudioData::NativeEndian>; | |||
| using NativeFloat32 = AudioData::Format<AudioData::Float32, AudioData::NativeEndian>; | |||
| while (! threadShouldExit()) | |||
| { | |||
| if (inputDevice != nullptr) | |||
| @@ -339,12 +342,9 @@ public: | |||
| jshort* const src = env->GetShortArrayElements (audioBuffer, nullptr); | |||
| AudioData::deinterleaveSamples<AudioData::Int16, AudioData::NativeEndian, | |||
| AudioData::Float32, AudioData::NativeEndian> (reinterpret_cast<const uint16*> (src), | |||
| numDeviceInputChannels, | |||
| inputChannelBuffer.getArrayOfWritePointers(), | |||
| inputChannelBuffer.getNumChannels(), | |||
| actualBufferSize); | |||
| AudioData::deinterleaveSamples (AudioData::InterleavedSource<NativeInt16> { reinterpret_cast<const uint16*> (src), numDeviceInputChannels }, | |||
| AudioData::NonInterleavedDest<NativeFloat32> { inputChannelBuffer.getArrayOfWritePointers(), inputChannelBuffer.getNumChannels() }, | |||
| actualBufferSize); | |||
| env->ReleaseShortArrayElements (audioBuffer, src, 0); | |||
| } | |||
| @@ -374,12 +374,9 @@ public: | |||
| jshort* const dest = env->GetShortArrayElements (audioBuffer, nullptr); | |||
| AudioData::interleaveSamples<AudioData::Float32, AudioData::NativeEndian, | |||
| AudioData::Int16, AudioData::NativeEndian> (outputChannelBuffer.getArrayOfReadPointers(), | |||
| outputChannelBuffer.getNumChannels(), | |||
| reinterpret_cast<uint16*> (dest), | |||
| numDeviceOutputChannels, | |||
| actualBufferSize); | |||
| AudioData::interleaveSamples (AudioData::NonInterleavedSource<NativeFloat32> { outputChannelBuffer.getArrayOfReadPointers(), outputChannelBuffer.getNumChannels() }, | |||
| AudioData::InterleavedDest<NativeInt16> { reinterpret_cast<uint16*> (dest), numDeviceOutputChannels }, | |||
| actualBufferSize); | |||
| env->ReleaseShortArrayElements (audioBuffer, dest, 0); | |||
| jint numWritten = env->CallIntMethod (outputDevice, AudioTrack.write, audioBuffer, 0, actualBufferSize * numDeviceOutputChannels); | |||
| @@ -44,28 +44,25 @@ struct OboeAudioIODeviceBufferHelpers<int16> | |||
| static bool referAudioBufferDirectlyToOboeIfPossible (int16*, AudioBuffer<float>&, int) { return false; } | |||
| using NativeInt16 = AudioData::Format<AudioData::Int16, AudioData::NativeEndian>; | |||
| using NativeFloat32 = AudioData::Format<AudioData::Float32, AudioData::NativeEndian>; | |||
| static void convertFromOboe (const int16* srcInterleaved, AudioBuffer<float>& audioBuffer, int numSamples) | |||
| { | |||
| const auto numChannels = audioBuffer.getNumChannels(); | |||
| AudioData::deinterleaveSamples<AudioData::Int16, AudioData::NativeEndian, | |||
| AudioData::Float32, AudioData::NativeEndian> (reinterpret_cast<const uint16*> (srcInterleaved), | |||
| numChannels, | |||
| audioBuffer.getArrayOfWritePointers(), | |||
| numChannels, | |||
| numSamples); | |||
| AudioData::deinterleaveSamples (AudioData::InterleavedSource<NativeInt16> { reinterpret_cast<const uint16*> (srcInterleaved), numChannels }, | |||
| AudioData::NonInterleavedDest<NativeFloat32> { audioBuffer.getArrayOfWritePointers(), numChannels }, | |||
| numSamples); | |||
| } | |||
| static void convertToOboe (const AudioBuffer<float>& audioBuffer, int16* dstInterleaved, int numSamples) | |||
| { | |||
| const auto numChannels = audioBuffer.getNumChannels(); | |||
| AudioData::interleaveSamples<AudioData::Float32, AudioData::NativeEndian, | |||
| AudioData::Int16, AudioData::NativeEndian> (audioBuffer.getArrayOfReadPointers(), | |||
| numChannels, | |||
| reinterpret_cast<uint16*> (dstInterleaved), | |||
| numChannels, | |||
| numSamples); | |||
| AudioData::interleaveSamples (AudioData::NonInterleavedSource<NativeFloat32> { audioBuffer.getArrayOfReadPointers(), numChannels }, | |||
| AudioData::InterleavedDest<NativeInt16> { reinterpret_cast<uint16*> (dstInterleaved), numChannels }, | |||
| numSamples); | |||
| } | |||
| }; | |||
| @@ -87,6 +84,8 @@ struct OboeAudioIODeviceBufferHelpers<float> | |||
| return false; | |||
| } | |||
| using Format = AudioData::Format<AudioData::Float32, AudioData::NativeEndian>; | |||
| static void convertFromOboe (const float* srcInterleaved, AudioBuffer<float>& audioBuffer, int numSamples) | |||
| { | |||
| auto numChannels = audioBuffer.getNumChannels(); | |||
| @@ -96,12 +95,9 @@ struct OboeAudioIODeviceBufferHelpers<float> | |||
| // No need to convert, we instructed the buffer to point to the src data directly already | |||
| jassert (audioBuffer.getWritePointer (0) != srcInterleaved); | |||
| AudioData::deinterleaveSamples<AudioData::Float32, AudioData::NativeEndian, | |||
| AudioData::Float32, AudioData::NativeEndian> (srcInterleaved, | |||
| numChannels, | |||
| audioBuffer.getArrayOfWritePointers(), | |||
| numChannels, | |||
| numSamples); | |||
| AudioData::deinterleaveSamples (AudioData::InterleavedSource<Format> { srcInterleaved, numChannels }, | |||
| AudioData::NonInterleavedDest<Format> { audioBuffer.getArrayOfWritePointers(), numChannels }, | |||
| numSamples); | |||
| } | |||
| } | |||
| @@ -114,12 +110,9 @@ struct OboeAudioIODeviceBufferHelpers<float> | |||
| // No need to convert, we instructed the buffer to point to the src data directly already | |||
| jassert (audioBuffer.getReadPointer (0) != dstInterleaved); | |||
| AudioData::interleaveSamples<AudioData::Float32, AudioData::NativeEndian, | |||
| AudioData::Float32, AudioData::NativeEndian> (audioBuffer.getArrayOfReadPointers(), | |||
| numChannels, | |||
| dstInterleaved, | |||
| numChannels, | |||
| numSamples); | |||
| AudioData::interleaveSamples (AudioData::NonInterleavedSource<Format> { audioBuffer.getArrayOfReadPointers(), numChannels }, | |||
| AudioData::InterleavedDest<Format> { dstInterleaved, numChannels }, | |||
| numSamples); | |||
| } | |||
| } | |||
| }; | |||
| @@ -194,28 +194,25 @@ struct BufferHelpers<int16> | |||
| static void prepareCallbackBuffer (AudioBuffer<float>&, int16*) {} | |||
| using LittleEndianInt16 = AudioData::Format<AudioData::Int16, AudioData::LittleEndian>; | |||
| using NativeFloat32 = AudioData::Format<AudioData::Float32, AudioData::NativeEndian>; | |||
| static void convertFromOpenSL (const int16* srcInterleaved, AudioBuffer<float>& audioBuffer) | |||
| { | |||
| const auto numChannels = audioBuffer.getNumChannels(); | |||
| AudioData::deinterleaveSamples<AudioData::Int16, AudioData::LittleEndian, | |||
| AudioData::Float32, AudioData::NativeEndian> (reinterpret_cast<const uint16*> (srcInterleaved), | |||
| numChannels, | |||
| audioBuffer.getArrayOfWritePointers(), | |||
| numChannels, | |||
| audioBuffer.getNumSamples()); | |||
| AudioData::deinterleaveSamples (AudioData::InterleavedSource<LittleEndianInt16> { reinterpret_cast<const uint16*> (srcInterleaved), numChannels }, | |||
| AudioData::NonInterleavedDest<NativeFloat32> { audioBuffer.getArrayOfWritePointers(), numChannels }, | |||
| audioBuffer.getNumSamples()); | |||
| } | |||
| static void convertToOpenSL (const AudioBuffer<float>& audioBuffer, int16* dstInterleaved) | |||
| { | |||
| const auto numChannels = audioBuffer.getNumChannels(); | |||
| AudioData::interleaveSamples<AudioData::Float32, AudioData::NativeEndian, | |||
| AudioData::Int16, AudioData::LittleEndian> (audioBuffer.getArrayOfReadPointers(), | |||
| numChannels, | |||
| reinterpret_cast<uint16*> (dstInterleaved), | |||
| numChannels, | |||
| audioBuffer.getNumSamples()); | |||
| AudioData::interleaveSamples (AudioData::NonInterleavedSource<NativeFloat32> { audioBuffer.getArrayOfReadPointers(), numChannels }, | |||
| AudioData::InterleavedDest<LittleEndianInt16> { reinterpret_cast<uint16*> (dstInterleaved), numChannels }, | |||
| audioBuffer.getNumSamples()); | |||
| } | |||
| }; | |||
| @@ -244,6 +241,9 @@ struct BufferHelpers<float> | |||
| audioBuffer.setDataToReferTo (&native, 1, audioBuffer.getNumSamples()); | |||
| } | |||
| using LittleEndianFloat32 = AudioData::Format<AudioData::Float32, AudioData::LittleEndian>; | |||
| using NativeFloat32 = AudioData::Format<AudioData::Float32, AudioData::NativeEndian>; | |||
| static void convertFromOpenSL (const float* srcInterleaved, AudioBuffer<float>& audioBuffer) | |||
| { | |||
| const auto numChannels = audioBuffer.getNumChannels(); | |||
| @@ -254,12 +254,9 @@ struct BufferHelpers<float> | |||
| return; | |||
| } | |||
| AudioData::deinterleaveSamples<AudioData::Float32, AudioData::LittleEndian, | |||
| AudioData::Float32, AudioData::NativeEndian> (srcInterleaved, | |||
| numChannels, | |||
| audioBuffer.getArrayOfWritePointers(), | |||
| numChannels, | |||
| audioBuffer.getNumSamples()); | |||
| AudioData::deinterleaveSamples (AudioData::InterleavedSource<LittleEndianFloat32> { srcInterleaved, numChannels }, | |||
| AudioData::nonInterleavedDest<NativeFloat32> { audioBuffer.getArrayOfWritePointers(), numChannels }, | |||
| audioBuffer.getNumSamples()); | |||
| } | |||
| static void convertToOpenSL (const AudioBuffer<float>& audioBuffer, float* dstInterleaved) | |||
| @@ -272,12 +269,9 @@ struct BufferHelpers<float> | |||
| return; | |||
| } | |||
| AudioData::interleaveSamples<AudioData::Float32, AudioData::NativeEndian, | |||
| AudioData::Float32, AudioData::LittleEndian> (audioBuffer.getArrayOfReadPointers(), | |||
| numChannels, | |||
| dstInterleaved, | |||
| numChannels, | |||
| audioBuffer.getNumSamples()); | |||
| AudioData::interleaveSamples (AudioData::NonInterleavedSource<NativeFloat32> { audioBuffer.getArrayOfReadPointers(), numChannels }, | |||
| AudioData::InterleavedDest<LittleEndianFloat32> { dstInterleaved, numChannels }, | |||
| audioBuffer.getNumSamples()); | |||
| } | |||
| }; | |||
| @@ -132,10 +132,9 @@ private: | |||
| source->source->getNextAudioBlock (info); | |||
| AudioData::interleaveSamples<AudioData::Float32, AudioData::NativeEndian, | |||
| AudioData::Int16, AudioData::LittleEndian> (tempBuffer.getArrayOfReadPointers(), 2, | |||
| reinterpret_cast<uint16*> (buffer), 2, | |||
| numSamples); | |||
| AudioData::interleaveSamples (AudioData::NonInterleavedSource<AudioData::Float32, AudioData::NativeEndian> { tempBuffer.getArrayOfReadPointers(), 2 }, | |||
| AudioData::InterleavedDest<AudioData::Int16, AudioData::LittleEndian> { reinterpret_cast<uint16*> (buffer), 2 }, | |||
| numSamples); | |||
| source->readPosition += numSamples; | |||
| } | |||
| @@ -388,10 +388,9 @@ bool AudioCDBurner::addAudioTrack (AudioSource* audioSource, int numSamples) | |||
| buffer.clear (bytesPerBlock); | |||
| AudioData::interleaveSamples<AudioData::Float32, AudioData::NativeEndian, | |||
| AudioData::Int16, AudioData::LittleEndian> (sourceBuffer.getArrayOfReadPointers(), 2, | |||
| reinterpret_cast<uint16*> (buffer), 2, | |||
| samplesPerBlock); | |||
| AudioData::interleaveSamples (AudioData::NonInterleavedSource<AudioData::Float32, AudioData::NativeEndian> { sourceBuffer.getArrayOfReadPointers(), 2 }, | |||
| AudioData::InterleavedDest<AudioData::Int16, Audiodata::LittleEndian> { reinterpret_cast<uint16*> (buffer), 2 }, | |||
| samplesPerBlock); | |||
| hr = pimpl->redbook->AddAudioTrackBlocks (buffer, bytesPerBlock); | |||