hrev43804 adds 1 changeset to branch 'master' old head: e766693eb0fe789eae0b729c7c5d5400018aa328 new head: ea81d6eaf00849fcf8bb46d5e2c2f59142dfc19b ---------------------------------------------------------------------------- ea81d6e: multi_audio: Add multiple Audio In Feature, implement listed TODO Signed-off-by: Jérôme Duval <jerome.duval@xxxxxxxxx> [ Jerome Leveque <leveque.jerome@xxxxxxxxx> ] ---------------------------------------------------------------------------- Revision: hrev43804 Commit: ea81d6eaf00849fcf8bb46d5e2c2f59142dfc19b URL: http://cgit.haiku-os.org/haiku/commit/?id=ea81d6e Author: Jerome Leveque <leveque.jerome@xxxxxxxxx> Date: Tue Jan 24 10:58:59 2012 UTC Committer: Jérôme Duval <jerome.duval@xxxxxxxxx> Commit-Date: Tue Feb 28 23:36:05 2012 UTC ---------------------------------------------------------------------------- 5 files changed, 900 insertions(+), 220 deletions(-) .../media/media-add-ons/multi_audio/Jamfile | 1 + .../media-add-ons/multi_audio/MultiAudioNode.cpp | 320 +++------ .../media-add-ons/multi_audio/MultiAudioNode.h | 9 +- .../media/media-add-ons/multi_audio/Resampler.cpp | 645 ++++++++++++++++ .../media/media-add-ons/multi_audio/Resampler.h | 145 ++++ ---------------------------------------------------------------------------- diff --git a/src/add-ons/media/media-add-ons/multi_audio/Jamfile b/src/add-ons/media/media-add-ons/multi_audio/Jamfile index 84b8641..7f116b7 100644 --- a/src/add-ons/media/media-add-ons/multi_audio/Jamfile +++ b/src/add-ons/media/media-add-ons/multi_audio/Jamfile @@ -13,6 +13,7 @@ Addon hmulti_audio.media_addon : MultiAudioDevice.cpp MultiAudioNode.cpp MultiAudioUtility.cpp + Resampler.cpp TimeComputer.cpp : be media $(TARGET_LIBSUPC++) ; diff --git a/src/add-ons/media/media-add-ons/multi_audio/MultiAudioNode.cpp b/src/add-ons/media/media-add-ons/multi_audio/MultiAudioNode.cpp index 44b9b5a..d417a88 100644 --- a/src/add-ons/media/media-add-ons/multi_audio/MultiAudioNode.cpp +++ b/src/add-ons/media/media-add-ons/multi_audio/MultiAudioNode.cpp @@ -24,12 +24,14 @@ # define PRINTING #endif #include "debug.h" +#include "Resampler.h" #define PARAMETER_ID_INPUT_FREQUENCY 1 #define PARAMETER_ID_OUTPUT_FREQUENCY 2 +//This represent an hardware output class node_input { public: node_input(media_input& input, media_format format); @@ -39,12 +41,14 @@ public: media_input fInput; media_format fPreferredFormat; media_format fFormat; - uint32 fBufferCycle; + volatile uint32 fBufferCycle; multi_buffer_info fOldBufferInfo; BBuffer* fBuffer; + Resampler *fResampler; }; +//This represent an hardware input class node_output { public: node_output(media_output& output, media_format format); @@ -60,6 +64,7 @@ public: uint64 fSamplesSent; volatile uint32 fBufferCycle; multi_buffer_info fOldBufferInfo; + Resampler *fResampler; }; @@ -115,6 +120,7 @@ node_input::node_input(media_input& input, media_format format) fPreferredFormat = format; fBufferCycle = 1; fBuffer = NULL; + fResampler = NULL; } @@ -136,6 +142,7 @@ node_output::node_output(media_output& output, media_format format) fOutput = output; fPreferredFormat = format; fBufferCycle = 1; + fResampler = NULL; } @@ -351,6 +358,10 @@ MultiAudioNode::NodeRegistered() currentInput = new node_input(*input, fOutputPreferredFormat); currentInput->fPreferredFormat.u.raw_audio.channel_count = 1; currentInput->fInput.format = currentInput->fPreferredFormat; + delete currentInput->fResampler; + currentInput->fResampler = new + Resampler(currentInput->fPreferredFormat.AudioFormat(), + fOutputPreferredFormat.AudioFormat()); currentInput->fChannelId = fDevice->Description().channels[i].channel_id; fInputs.AddItem(currentInput); @@ -397,6 +408,11 @@ MultiAudioNode::NodeRegistered() currentOutput = new node_output(*output, fInputPreferredFormat); currentOutput->fPreferredFormat.u.raw_audio.channel_count = 1; currentOutput->fOutput.format = currentOutput->fPreferredFormat; + delete currentOutput->fResampler; + currentOutput->fResampler = new + Resampler(fInputPreferredFormat.AudioFormat(), + currentOutput->fPreferredFormat.AudioFormat()); + currentOutput->fChannelId = fDevice->Description().channels[i].channel_id; fOutputs.AddItem(currentOutput); @@ -1725,8 +1741,6 @@ MultiAudioNode::_OutputThread() CALLED(); multi_buffer_info bufferInfo; bufferInfo.info_size = sizeof(multi_buffer_info); - bufferInfo._reserved_0 = 0; - bufferInfo._reserved_1 = 2; bufferInfo.playback_buffer_cycle = 0; bufferInfo.record_buffer_cycle = 0; @@ -1758,8 +1772,7 @@ MultiAudioNode::_OutputThread() for (int32 i = 0; i < fInputs.CountItems(); i++) { node_input* input = (node_input*)fInputs.ItemAt(i); - if (bufferInfo._reserved_0 == input->fChannelId - && bufferInfo.playback_buffer_cycle >= 0 + if (bufferInfo.playback_buffer_cycle >= 0 && bufferInfo.playback_buffer_cycle < fDevice->BufferList().return_playback_buffers && (input->fOldBufferInfo.playback_buffer_cycle @@ -1814,8 +1827,7 @@ MultiAudioNode::_OutputThread() // buffer if (RunState() == BMediaEventLooper::B_STARTED && output->fOutput.destination != media_destination::null) { - if (bufferInfo._reserved_1 == output->fChannelId - && bufferInfo.record_buffer_cycle >= 0 + if (bufferInfo.record_buffer_cycle >= 0 && bufferInfo.record_buffer_cycle < fDevice->BufferList().return_record_buffers && (output->fOldBufferInfo.record_buffer_cycle @@ -1823,6 +1835,8 @@ MultiAudioNode::_OutputThread() || fDevice->BufferList().return_record_buffers == 1)) { //PRINT(("record_buffer_cycle ok\n")); + output->fBufferCycle = bufferInfo.record_buffer_cycle; + // Get the next buffer of data BBuffer* buffer = _FillNextBuffer(bufferInfo, *output); if (buffer != NULL) { @@ -1889,6 +1903,17 @@ MultiAudioNode::_WriteZeros(node_input& input, uint32 bufferCycle) } break; + case media_raw_audio_format::B_AUDIO_DOUBLE: + for (uint32 channel = 0; channel < channelCount; channel++) { + char* dest = _PlaybackBuffer(bufferCycle, + input.fChannelId + channel); + for (uint32 i = bufferSize; i > 0; i--) { + *(double*)dest = 0; + dest += stride; + } + } + break; + case media_raw_audio_format::B_AUDIO_INT: for (uint32 channel = 0; channel < channelCount; channel++) { char* dest = _PlaybackBuffer(bufferCycle, @@ -1911,6 +1936,28 @@ MultiAudioNode::_WriteZeros(node_input& input, uint32 bufferCycle) } break; + case media_raw_audio_format::B_AUDIO_UCHAR: + for (uint32 channel = 0; channel < channelCount; channel++) { + char* dest = _PlaybackBuffer(bufferCycle, + input.fChannelId + channel); + for (uint32 i = bufferSize; i > 0; i--) { + *(uint8*)dest = 128; + dest += stride; + } + } + break; + + case media_raw_audio_format::B_AUDIO_CHAR: + for (uint32 channel = 0; channel < channelCount; channel++) { + char* dest = _PlaybackBuffer(bufferCycle, + input.fChannelId + channel); + for (uint32 i = bufferSize; i > 0; i--) { + *(int8*)dest = 0; + dest += stride; + } + } + break; + default: fprintf(stderr, "ERROR in WriteZeros format not handled\n"); } @@ -1929,218 +1976,35 @@ MultiAudioNode::_FillWithZeros(node_input& input) void MultiAudioNode::_FillNextBuffer(node_input& input, BBuffer* buffer) { - // TODO: simplify this, or put it into a static function to remove - // the need for checking all over again + uint32 channelCount = input.fInput.format.u.raw_audio.channel_count; + size_t inputSampleSize = input.fInput.format.u.raw_audio.format + & media_raw_audio_format::B_AUDIO_SIZE_MASK; uint32 bufferSize = fDevice->BufferList().return_playback_buffer_size; - if (buffer->SizeUsed() - / (input.fInput.format.u.raw_audio.format - & media_raw_audio_format::B_AUDIO_SIZE_MASK) - / input.fInput.format.u.raw_audio.channel_count != bufferSize) { + if (buffer->SizeUsed() / inputSampleSize / channelCount != bufferSize) { _WriteZeros(input, input.fBufferCycle); return; } - switch (input.fInput.format.u.raw_audio.format) { - case media_raw_audio_format::B_AUDIO_FLOAT: - switch (input.fFormat.u.raw_audio.format) { - case media_raw_audio_format::B_AUDIO_FLOAT: - { - size_t frameSize = input.fInput.format.u.raw_audio - .channel_count * sizeof(float); - size_t stride = _PlaybackStride(input.fBufferCycle, - input.fChannelId); - //PRINT(("stride : %i, frame_size : %i, return_playback_buffer_size : %i\n", stride, frame_size, fDevice->BufferList().return_playback_buffer_size)); - for (uint32 channel = 0; channel - < input.fInput.format.u.raw_audio.channel_count; - channel++) { - char* dest = _PlaybackBuffer(input.fBufferCycle, - input.fChannelId + channel); - char* src = (char*)buffer->Data() - + channel * sizeof(float); - - for (uint32 i = bufferSize; i > 0; i--) { - *(float *)dest = *(float *)src; - dest += stride; - src += frameSize; - } - } - break; - } - - case media_raw_audio_format::B_AUDIO_SHORT: - if (input.fInput.format.u.raw_audio.channel_count == 2) { - int16* dest1 = (int16*)_PlaybackBuffer( - input.fBufferCycle, input.fChannelId); - int16* dest2 = (int16*)_PlaybackBuffer( - input.fBufferCycle, input.fChannelId + 1); - float* src = (float*)buffer->Data(); - if (_PlaybackStride(input.fBufferCycle, - input.fChannelId) == sizeof(int16) - && _PlaybackStride(input.fBufferCycle, - input.fChannelId + 1) == sizeof(int16)) { - //PRINT(("FillNextBuffer : 2 channels strides 2\n")); - for (uint32 i = bufferSize; i > 0; i--) { - *dest1++ = int16(32767 * *src++); - *dest2++ = int16(32767 * *src++); - } - } else if (_PlaybackStride(input.fBufferCycle, - input.fChannelId) == 2 * sizeof(int16) - && _PlaybackStride(input.fBufferCycle, - input.fChannelId + 1) == 2 * sizeof(int16) - && dest1 + 1 == dest2) { - //PRINT(("FillNextBuffer : 2 channels strides 4\n")); - for (uint32 i = 2 * bufferSize; i > 0; i--) - *dest1++ = int16(32767 * *src++); - } else { - //PRINT(("FillNextBuffer : 2 channels strides != 2\n")); - size_t stride1 = _PlaybackStride(input.fBufferCycle, - input.fChannelId) / sizeof(int16); - size_t stride2 = _PlaybackStride(input.fBufferCycle, - input.fChannelId + 1) / sizeof(int16); - for (uint32 i = bufferSize; i > 0; i--) { - *dest1 = int16(32767 * *src++); - *dest2 = int16(32767 * *src++); - dest1 += stride1; - dest2 += stride2; - } - } - } else { - size_t frameSize = input.fInput.format.u - .raw_audio.channel_count * sizeof(int16); - size_t stride = _PlaybackStride(input.fBufferCycle, - input.fChannelId); - //PRINT(("stride : %i, frame_size : %i, return_playback_buffer_size : %i\n", stride, frame_size, fDevice->BufferList().return_playback_buffer_size)); - for (uint32 channel = 0; channel < - input.fInput.format.u.raw_audio.channel_count; - channel++) { - char* dest = _PlaybackBuffer(input.fBufferCycle, - input.fChannelId + channel); - char* src = (char*)buffer->Data() - + channel * sizeof(int16); - - for (uint32 i = bufferSize; i > 0; i--) { - *(int16*)dest = int16(32767 * *(float*)src); - dest += stride; - src += frameSize; - } - } - } - break; + if (channelCount != input.fFormat.u.raw_audio.channel_count) { + PRINT(("Channel count is different")); + return; + } - case media_raw_audio_format::B_AUDIO_INT: - default: - break; - } - break; + if (input.fResampler != NULL) { + size_t srcStride = channelCount * inputSampleSize; - case media_raw_audio_format::B_AUDIO_INT: - switch (input.fFormat.u.raw_audio.format) { - case media_raw_audio_format::B_AUDIO_INT: - { - size_t frameSize = input.fInput.format.u.raw_audio - .channel_count * sizeof(int32); - size_t stride = _PlaybackStride(input.fBufferCycle, - input.fChannelId); - //PRINT(("stride : %i, frame_size : %i, return_playback_buffer_size : %i\n", stride, frame_size, fDevice->BufferList().return_playback_buffer_size)); - for (uint32 channel = 0; channel - < input.fInput.format.u.raw_audio.channel_count; - channel++) { - char* dest = _PlaybackBuffer(input.fBufferCycle, + for (uint32 channel = 0; channel < channelCount; channel++) { + char* src = (char*)buffer->Data() + channel * inputSampleSize; + char* dst = _PlaybackBuffer(input.fBufferCycle, + input.fChannelId + channel); + size_t dstStride = _PlaybackStride(input.fBufferCycle, input.fChannelId + channel); - char* src = (char*)buffer->Data() - + channel * sizeof(int32); - - for (uint32 i = bufferSize; i > 0; i--) { - *(int32 *)dest = *(int32 *)src; - dest += stride; - src += frameSize; - } - } - break; - } - case media_raw_audio_format::B_AUDIO_SHORT: - case media_raw_audio_format::B_AUDIO_FLOAT: - default: - break; - } - break; - - case media_raw_audio_format::B_AUDIO_SHORT: - switch (input.fFormat.u.raw_audio.format) { - case media_raw_audio_format::B_AUDIO_SHORT: - if (input.fInput.format.u.raw_audio.channel_count == 2) { - int16* dest1 = (int16*)_PlaybackBuffer( - input.fBufferCycle, input.fChannelId); - int16* dest2 = (int16*)_PlaybackBuffer( - input.fBufferCycle, input.fChannelId + 1); - int16* src = (int16*)buffer->Data(); - if (_PlaybackStride(input.fBufferCycle, - input.fChannelId) == sizeof(int16) - && _PlaybackStride(input.fBufferCycle, - input.fChannelId + 1) == sizeof(int16)) { - //PRINT(("FillNextBuffer : 2 channels strides 2\n")); - for (uint32 i = bufferSize; i > 0; i--) { - *dest1++ = *src++; - *dest2++ = *src++; - } - } else if (_PlaybackStride(input.fBufferCycle, - input.fChannelId) == 2 * sizeof(int16) - && _PlaybackStride(input.fBufferCycle, - input.fChannelId + 1) == 2 * sizeof(int16) - && dest1 + 1 == dest2) { - //PRINT(("FillNextBuffer : 2 channels strides 4\n")); - memcpy(dest1, src, - bufferSize * 2 * sizeof(int16)); - } else { - //PRINT(("FillNextBuffer : 2 channels strides != 2\n")); - size_t stride1 = _PlaybackStride( - input.fBufferCycle, input.fChannelId) / 2; - size_t stride2 = _PlaybackStride( - input.fBufferCycle, input.fChannelId + 1) - / 2; - - for (uint32 i = bufferSize; i > 0; i--) { - *dest1 = *src++; - *dest2 = *src++; - dest1 += stride1; - dest2 += stride2; - } - } - } else { - size_t frameSize = input.fInput.format.u - .raw_audio.channel_count * sizeof(int16); - size_t stride = _PlaybackStride(input.fBufferCycle, - input.fChannelId); - //PRINT(("stride : %i, frame_size : %i, return_playback_buffer_size : %i\n", stride, frame_size, fDevice->BufferList().return_playback_buffer_size)); - for (uint32 channel = 0; channel - < input.fInput.format.u.raw_audio.channel_count; - channel++) { - char* dest = _PlaybackBuffer(input.fBufferCycle, - input.fChannelId + channel); - char* src = (char*)buffer->Data() - + channel * sizeof(int16); - - for (uint32 i = bufferSize; i > 0; i--) { - *(int16*)dest = *(int16*)src; - dest += stride; - src += frameSize; - } - } - } - break; - - case media_raw_audio_format::B_AUDIO_FLOAT: - case media_raw_audio_format::B_AUDIO_INT: - default: - break; - } - break; - case media_raw_audio_format::B_AUDIO_UCHAR: - default: - break; + input.fResampler->Resample(src, srcStride, + dst, dstStride, bufferSize); + } } } @@ -2219,7 +2083,7 @@ MultiAudioNode::_UpdateTimeSource(multi_buffer_info& info, BBuffer* -MultiAudioNode::_FillNextBuffer(multi_buffer_info &info, node_output &channel) +MultiAudioNode::_FillNextBuffer(multi_buffer_info &info, node_output &output) { //CALLED(); // get a buffer from our buffer group @@ -2227,15 +2091,16 @@ MultiAudioNode::_FillNextBuffer(multi_buffer_info &info, node_output &channel) //PRINT(("MBI.record_buffer_cycle : %i\n", MBI.record_buffer_cycle)); //PRINT(("MBI.recorded_real_time : %i\n", MBI.recorded_real_time)); //PRINT(("MBI.recorded_frames_count : %i\n", MBI.recorded_frames_count)); - if (!channel.fBufferGroup) + if (!output.fBufferGroup) return NULL; - BBuffer* buffer = channel.fBufferGroup->RequestBuffer( - channel.fOutput.format.u.raw_audio.buffer_size, BufferDuration()); + BBuffer* buffer = output.fBufferGroup->RequestBuffer( + output.fOutput.format.u.raw_audio.buffer_size, BufferDuration()); if (buffer == NULL) { // If we fail to get a buffer (for example, if the request times out), // we skip this buffer and go on to the next, to avoid locking up the // control thread. + fprintf(stderr, "Buffer is null"); return NULL; } @@ -2246,17 +2111,34 @@ MultiAudioNode::_FillNextBuffer(multi_buffer_info &info, node_output &channel) if (TimeSource() == NULL) fprintf(stderr, "TimeSource() NULL\n"); - // now fill it with data, continuing where the last buffer left off - memcpy(buffer->Data(), - fDevice->BufferList().record_buffers[info.record_buffer_cycle] - [channel.fChannelId - - fDevice->Description().output_channel_count].base, - channel.fOutput.format.u.raw_audio.buffer_size); + uint32 channelCount = output.fOutput.format.u.raw_audio.channel_count; + size_t outputSampleSize = output.fOutput.format.u.raw_audio.format + & media_raw_audio_format::B_AUDIO_SIZE_MASK; + + uint32 bufferSize = fDevice->BufferList().return_record_buffer_size; + + if (output.fResampler != NULL) { + size_t dstStride = channelCount * outputSampleSize; + + uint32 channelId = output.fChannelId + - fDevice->Description().output_channel_count; + + for (uint32 channel = 0; channel < channelCount; channel++) { + char* src = _RecordBuffer(output.fBufferCycle, + channelId + channel); + size_t srcStride = _RecordStride(output.fBufferCycle, + channelId + channel); + char* dst = (char*)buffer->Data() + channel * outputSampleSize; + + output.fResampler->Resample(src, srcStride, dst, dstStride, + bufferSize); + } + } // fill in the buffer header media_header* header = buffer->Header(); header->type = B_MEDIA_RAW_AUDIO; - header->size_used = channel.fOutput.format.u.raw_audio.buffer_size; + header->size_used = output.fOutput.format.u.raw_audio.buffer_size; header->time_source = TimeSource()->ID(); header->start_time = PerformanceTimeFor(info.recorded_real_time); diff --git a/src/add-ons/media/media-add-ons/multi_audio/MultiAudioNode.h b/src/add-ons/media/media-add-ons/multi_audio/MultiAudioNode.h index 34e9e1b..473c77b 100644 --- a/src/add-ons/media/media-add-ons/multi_audio/MultiAudioNode.h +++ b/src/add-ons/media/media-add-ons/multi_audio/MultiAudioNode.h @@ -166,6 +166,13 @@ private: { return fDevice->BufferList().playback_buffers [cycle][channel].stride; } + char* _RecordBuffer(int32 cycle, int32 channel) + { return fDevice->BufferList().record_buffers + [cycle][channel].base; } + uint32 _RecordStride(int32 cycle, int32 channel) + { return fDevice->BufferList().record_buffers + [cycle][channel].stride; } + void _WriteZeros(node_input& input, uint32 bufferCycle); void _FillWithZeros(node_input& input); void _FillNextBuffer(node_input& channel, @@ -178,7 +185,7 @@ private: void _AllocateBuffers(node_output& channel); BBuffer* _FillNextBuffer(multi_buffer_info& info, - node_output& channel); + node_output& output); void _UpdateTimeSource(multi_buffer_info& info, multi_buffer_info& oldInfo, node_input& input); diff --git a/src/add-ons/media/media-add-ons/multi_audio/Resampler.cpp b/src/add-ons/media/media-add-ons/multi_audio/Resampler.cpp new file mode 100644 index 0000000..780ec8d --- /dev/null +++ b/src/add-ons/media/media-add-ons/multi_audio/Resampler.cpp @@ -0,0 +1,645 @@ +/* + * Copyright 2012 Jérôme Leveque + * Copyright 2012 Jérôme Duval + * Copyright 2003 Marcus Overhagen + * Distributed under the terms of the MIT License. + */ + + +#include "Resampler.h" +#include "MultiAudioUtility.h" +#include "debug.h" + + +/*! A simple resampling class for the multi_audio add-ons. + You pick the conversion function on object creation, + and then call the Resample() function, specifying data pointer, + offset (in bytes) to the next sample, and count of samples. +*/ + + +Resampler::Resampler(uint32 sourceFormat, uint32 destFormat) + : + fFunc(NULL) +{ + PRINT(("Resampler() in 0x%x, out 0x%x\n", (unsigned int)sourceFormat, + (unsigned int)destFormat)); + + switch (sourceFormat) { + case media_raw_audio_format::B_AUDIO_FLOAT: + switch (destFormat) { + case media_raw_audio_format::B_AUDIO_FLOAT: + fFunc = &Resampler::_CopyType2Type<float>; + break; + case media_raw_audio_format::B_AUDIO_DOUBLE: + fFunc = &Resampler::_CopyFloat2Double; + break; + case media_raw_audio_format::B_AUDIO_INT: + fFunc = &Resampler::_CopyFloat2Int; + break; + case media_raw_audio_format::B_AUDIO_SHORT: + fFunc = &Resampler::_CopyFloat2Short; + break; + case media_raw_audio_format::B_AUDIO_UCHAR: + fFunc = &Resampler::_CopyFloat2UChar; + break; + case media_raw_audio_format::B_AUDIO_CHAR: + fFunc = &Resampler::_CopyFloat2Char; + break; + } + break; + + case media_raw_audio_format::B_AUDIO_DOUBLE: + switch (destFormat) { + case media_raw_audio_format::B_AUDIO_FLOAT: + fFunc = &Resampler::_CopyDouble2Float; + break; + case media_raw_audio_format::B_AUDIO_DOUBLE: + fFunc = &Resampler::_CopyType2Type<double>; + break; + case media_raw_audio_format::B_AUDIO_INT: + fFunc = &Resampler::_CopyDouble2Int; + break; + case media_raw_audio_format::B_AUDIO_SHORT: + fFunc = &Resampler::_CopyDouble2Short; + break; + case media_raw_audio_format::B_AUDIO_UCHAR: + fFunc = &Resampler::_CopyDouble2UChar; + break; + case media_raw_audio_format::B_AUDIO_CHAR: + fFunc = &Resampler::_CopyDouble2Char; + break; + } + break; + + case media_raw_audio_format::B_AUDIO_INT: + switch (destFormat) { + case media_raw_audio_format::B_AUDIO_FLOAT: + fFunc = &Resampler::_CopyInt2Float; + break; + case media_raw_audio_format::B_AUDIO_DOUBLE: + fFunc = &Resampler::_CopyInt2Double; + break; + case media_raw_audio_format::B_AUDIO_INT: + fFunc = &Resampler::_CopyType2Type<int32>; + break; + case media_raw_audio_format::B_AUDIO_SHORT: + fFunc = &Resampler::_CopyInt2Short; + break; + case media_raw_audio_format::B_AUDIO_UCHAR: + fFunc = &Resampler::_CopyInt2UChar; + break; + case media_raw_audio_format::B_AUDIO_CHAR: + fFunc = &Resampler::_CopyInt2Char; + break; + } + break; + + case media_raw_audio_format::B_AUDIO_SHORT: + switch (destFormat) { + case media_raw_audio_format::B_AUDIO_FLOAT: + fFunc = &Resampler::_CopyShort2Float; + break; + case media_raw_audio_format::B_AUDIO_DOUBLE: + fFunc = &Resampler::_CopyShort2Double; + break; + case media_raw_audio_format::B_AUDIO_INT: + fFunc = &Resampler::_CopyShort2Int; + break; + case media_raw_audio_format::B_AUDIO_SHORT: + fFunc = &Resampler::_CopyType2Type<int16>; + break; + case media_raw_audio_format::B_AUDIO_UCHAR: + fFunc = &Resampler::_CopyShort2UChar; + break; + case media_raw_audio_format::B_AUDIO_CHAR: + fFunc = &Resampler::_CopyShort2Char; + break; + } + break; + + case media_raw_audio_format::B_AUDIO_UCHAR: + switch (destFormat) { + case media_raw_audio_format::B_AUDIO_FLOAT: + fFunc = &Resampler::_CopyUChar2Float; + break; + case media_raw_audio_format::B_AUDIO_DOUBLE: + fFunc = &Resampler::_CopyUChar2Double; + break; + case media_raw_audio_format::B_AUDIO_INT: + fFunc = &Resampler::_CopyUChar2Int; + break; + case media_raw_audio_format::B_AUDIO_SHORT: + fFunc = &Resampler::_CopyUChar2Short; + break; + case media_raw_audio_format::B_AUDIO_UCHAR: + fFunc = &Resampler::_CopyType2Type<uint8>; + break; + case media_raw_audio_format::B_AUDIO_CHAR: + fFunc = &Resampler::_CopyUChar2Char; + break; + } + break; + + case media_raw_audio_format::B_AUDIO_CHAR: + switch (destFormat) { + case media_raw_audio_format::B_AUDIO_FLOAT: + fFunc = &Resampler::_CopyChar2Float; + break; + case media_raw_audio_format::B_AUDIO_DOUBLE: + fFunc = &Resampler::_CopyChar2Double; + break; + case media_raw_audio_format::B_AUDIO_INT: + fFunc = &Resampler::_CopyChar2Int; + break; + case media_raw_audio_format::B_AUDIO_SHORT: + fFunc = &Resampler::_CopyChar2Short; + break; + case media_raw_audio_format::B_AUDIO_UCHAR: + fFunc = &Resampler::_CopyChar2UChar; + break; + case media_raw_audio_format::B_AUDIO_CHAR: + fFunc = &Resampler::_CopyType2Type<int8>; + break; + } + break; + } +} + + +Resampler::~Resampler() +{ +} + + +status_t +Resampler::InitCheck() const +{ + return fFunc != NULL ? B_OK : B_ERROR; +} + + +template<typename T> +void +Resampler::_CopyType2Type(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(T*)outputData = *(const T*)inputData; + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyFloat2Double(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(double*)outputData = *(const float*)inputData; + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyFloat2Int(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(int32*)outputData = (int32)(*(const float*)inputData * 2147483647.0f); + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + +void +Resampler::_CopyFloat2Short(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(int16*)outputData = (int16)(*(const float*)inputData * 32767.0f); + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyFloat2UChar(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(uint8*)outputData = (uint8)(128.0f + *(const float*)inputData * 127.0f); + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyFloat2Char(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(int8*)outputData = (int8)(*(const float*)inputData * 127.0f); + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyDouble2Float(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(float*)outputData = *(const double*)inputData; + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyDouble2Int(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(int32*)outputData = (int32)(*(const double*)inputData * 2147483647.0f); + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyDouble2Short(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(int16*)outputData = (int16)(*(const double*)inputData * 32767.0f); + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyDouble2UChar(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(uint8*)outputData = (uint8)(128.0f + *(const double*)inputData * 127.0f); + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyDouble2Char(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(int8*)outputData = (int8)(*(const double*)inputData * 127.0f); + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyShort2Float(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(float*)outputData = *(const int16*)inputData / 32767.0f; + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyShort2Double(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(double*)outputData = *(const int16*)inputData / 32767.0; + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyShort2Int(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(int32*)outputData = (int32)*(const int16*)inputData << 16; + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyShort2UChar(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(uint8*)outputData = 128 + (*(const int16*)inputData >> 8); + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyShort2Char(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(int8*)outputData = *(const int16*)inputData >> 8; + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyInt2Float(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(float*)outputData = *(const int32*)inputData / 2147483647.0f; + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyInt2Double(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(double*)outputData = *(const int32*)inputData / 2147483647.0; + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyInt2Short(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(int16*)outputData = *(const int32*)inputData >> 16; + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyInt2UChar(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(uint8*)outputData = 128 + (*(const int32*)inputData >> 24); + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyInt2Char(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(uint8*)outputData = *(const int32*)inputData >> 24; + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyUChar2Float(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(float*)outputData = (*(const uint8*)inputData - 128) / 127.0f; + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyUChar2Double(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(double*)outputData = (*(const uint8*)inputData - 128) / 127.0; + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyUChar2Short(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(int16*)outputData = (int16)(*(const uint8*)inputData - 128) << 8; + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyUChar2Int(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(int32*)outputData = (int32)(*(const uint8*)inputData - 128) << 24; + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyUChar2Char(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(int8*)outputData = *(const uint8*)inputData - 128; + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyChar2Float(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(float*)outputData = *(const int8*)inputData / 127.0f; + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyChar2Double(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(double*)outputData = *(const int8*)inputData / 127.0; + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyChar2Short(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(int16*)outputData = ((int16)*(const int8*)inputData) << 8; + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyChar2Int(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(int32*)outputData = ((int16)*(const int8*)inputData) << 24; + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + + +void +Resampler::_CopyChar2UChar(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + while (sampleCount > 0) { + *(uint8*)outputData = *(const int8*)inputData + 128; + + outputData = (void*)((uint8*)outputData + outputStride); + inputData = (void*)((uint8*)inputData + inputStride); + + sampleCount--; + } +} + diff --git a/src/add-ons/media/media-add-ons/multi_audio/Resampler.h b/src/add-ons/media/media-add-ons/multi_audio/Resampler.h new file mode 100644 index 0000000..d392bd8 --- /dev/null +++ b/src/add-ons/media/media-add-ons/multi_audio/Resampler.h @@ -0,0 +1,145 @@ +/* + * Copyright 2012 Jérôme Leveque + * Copyright 2003 Marcus Overhagen + * Distributed under the terms of the MIT License. + */ +#ifndef _MULTI_AUDIO_RESAMPLER_H +#define _MULTI_AUDIO_RESAMPLER_H + + +#include <MediaDefs.h> + + +class Resampler { +public: + Resampler(uint32 sourceFormat, + uint32 destFormat); + + virtual ~Resampler(); + + status_t InitCheck() const; + + void Resample(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + +protected: + //static functions for converting datas + template<typename T> void _CopyType2Type(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyFloat2Double(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyFloat2Short(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyFloat2Int(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyFloat2UChar(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyFloat2Char(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + + virtual void _CopyDouble2Float(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyDouble2Short(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyDouble2Int(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyDouble2UChar(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyDouble2Char(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + + virtual void _CopyInt2Float(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyInt2Double(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyInt2Short(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyInt2UChar(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyInt2Char(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + + virtual void _CopyShort2Float(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyShort2Double(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyShort2Int(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyShort2UChar(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyShort2Char(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + + virtual void _CopyUChar2Float(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyUChar2Double(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyUChar2Short(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyUChar2Int(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyUChar2Char(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + + virtual void _CopyChar2Float(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyChar2Double(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyChar2Short(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyChar2Int(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + virtual void _CopyChar2UChar(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); + +private: + void (Resampler::*fFunc)(const void *inputData, + uint32 inputStride, void *outputData, + uint32 outputStride, uint32 sampleCount); +}; + + +inline void +Resampler::Resample(const void *inputData, uint32 inputStride, + void *outputData, uint32 outputStride, uint32 sampleCount) +{ + if (this->InitCheck() != B_OK) + return; + (this->*fFunc)(inputData, inputStride, outputData, outputStride, + sampleCount); +} + + +#endif // _MULTI_AUDIO_RESAMPLER_H