multi_audio: Add multiple Audio In Feature, implement listed TODO

Signed-off-by: Jérôme Duval <[email protected]>
This commit is contained in:
Jerome Leveque
2012-02-29 00:36:05 +01:00
committed by Jérôme Duval
parent e766693eb0
commit ea81d6eaf0
5 changed files with 901 additions and 221 deletions
@@ -13,6 +13,7 @@ Addon hmulti_audio.media_addon :
MultiAudioDevice.cpp
MultiAudioNode.cpp
MultiAudioUtility.cpp
Resampler.cpp
TimeComputer.cpp
: be media $(TARGET_LIBSUPC++)
;
@@ -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,
if (channelCount != input.fFormat.u.raw_audio.channel_count) {
PRINT(("Channel count is different"));
return;
}
if (input.fResampler != NULL) {
size_t srcStride = channelCount * inputSampleSize;
for (uint32 channel = 0; channel < channelCount; channel++) {
char* src = (char*)buffer->Data() + channel * inputSampleSize;
char* dst = _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;
case media_raw_audio_format::B_AUDIO_INT:
default:
break;
}
break;
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,
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);
@@ -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);
@@ -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--;
}
}
@@ -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