multi_audio: Add multiple Audio In Feature, implement listed TODO
Signed-off-by: Jérôme Duval <[email protected]>
This commit is contained in:
committed by
Jérôme Duval
parent
e766693eb0
commit
ea81d6eaf0
@@ -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
|
||||
Reference in New Issue
Block a user