Portaudio回调函数示例
Portaudio Callback Function Example
我目前正在使用live555、mpg123和portaudio构建一个mp3流媒体/接收器,并刚刚开始流媒体、解码和播放mp3的概念。
我的问题是当我需要用portaudio播放声音时。我不知道如何编写一个回调函数来播放我解码的mp3。
这是我在某个地方找到并尝试过的回调函数,但它并没有给我带来好的结果(除了噪音和嗡嗡声)。
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
/* Cast data passed through stream to our structure. */
paTestData *data_struct = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned int i;
(void) inputBuffer; /* Prevent unused variable warning. */
for( i=0; i<framesPerBuffer; i++ )
{
if(data_struct->cursor < data_struct->num_frames)
{
out[i] = data_struct->data[data_struct->cursor];
data_struct->cursor++;
}
else
{
out[i] = 0; // if you've used up all the data, just fill the rest with silence.
//finished = paComplete;
}
}
return 0;
}
回调函数接收一个结构,该结构包含无符号字符数组中的解码数据和解码的字节数:
typedef struct
{
unsigned char* data;
unsigned long cursor;
unsigned long num_frames;
}
paTestData;
编解码器功能如下:
mpg123_decode(m,fBuffer,frameSize,out,OUTBUFF,&size);
因此,它以无符号字符(out)的形式返回数据,并在大小变量中解码字节。fBuffer是编码的数据,frameSize是编码的字节数。
我以与portaudio教程相同的方式配置了portaudio流:
err = Pa_OpenDefaultStream( &stream,
0, /* no input channels */
2, /* stereo output */
paFloat32, /* 32 bit floating point output */
SAMPLE_RATE,
paFramesPerBufferUnspecified, /* frames per buffer, i.e. the number
of sample frames that PortAudio will
request from the callback. Many apps
may want to use
paFramesPerBufferUnspecified, which
tells PortAudio to pick the best,
possibly changing, buffer size.*/
patestCallback, /* this is your callback function */
&paData ); /*This is a pointer that will be passed to
your callback*/
一个好的回调函数的例子将非常有用,但当然任何帮助都是值得赞赏的,
感谢
我认为您可以非常确信mpg123_decode
输出的实际音频数据格式不是无符号字符。很可能它是以这种方式声明为通用指针的。你应该研究一下实际的类型。它可能是你可以配置的。
我的第一个猜测是mpg123_decode
的输出是立体声16位int(假设是立体声源)。如果是这种情况,下面的代码可能会起作用。
请注意,我对您的代码做了最小的更改,以使其正常工作。这不是一个如何做到这一点的好例子。我的代码问题:
- 流样本格式是paFloat,尽管如果源是short,您可能只应该输出paInt16。
scale
变量用于转换为paFloat[-1,1]的正确范围 - 讨厌的强制转换将您的data_struct->数据保持为char*,即使如果源代码是short,它可能应该是short*
-
循环覆盖
framesPerBuffer*2
个样本(因为1帧是所有通道,我假设是立体声)。这并不能使代码变得非常清晰(查看其他PA示例,了解立体声通常是如何处理的)。static int patestCallback( const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *userData ) { /* Cast data passed through stream to our structure. */ paTestData *data_struct = (paTestData*)userData; float *out = (float*)outputBuffer; unsigned int i; (void) inputBuffer; /* Prevent unused variable warning. */ static const float scale = 1./32768.; for( i=0; i<framesPerBuffer*2; i++ ) // source and dest are interleaved { if(data_struct->cursor < data_struct->num_frames) { out[i] = *((short*)(&data_struct->data[data_struct->cursor])) * scale; data_struct->cursor += sizeof(short); } else { out[i] = 0; // if you've used up all the data, just fill the rest with silence. //finished = paComplete; } } return 0; }
相关文章:
- 以特征类型作为参数的泛型函数回调
- C# DllImport 调用非托管C++函数回调
- 为什么模板参数推导失败,std::函数回调的可变参数模板参数?
- std::包含 std::函数回调的多个包装器的向量不起作用
- 如何设置对类的私有函数的函数回调?
- 如何使用 c++11 函数回调声明多个模板参数
- sqlite3 更改函数回调参数 void* not用于 int* C++
- 如何知道 sqlite 中的函数"回调"是否返回了一些东西?
- Windows表单如何使用其他函数回调图表信息
- 如何在 c++ 结构中的 void* 变量中调用存储函数(回调)
- 将成员函数作为标准函数回调
- C++ 使用成员函数回调实现按钮
- std::函数回调,参数采用观察者模式(寄存器主题上的占位符)
- 使用可变参数模板从 Lua 函数回调 (C api) 中提取参数
- 在C++中使用派生类的静态方法作为函数回调
- 将libuv与函数结构一起使用,而不是函数回调
- 如何将函数回调传递给类成员
- c++类成员函数回调
- C++函数回调:无法从成员函数转换为函数签名
- 如何编写一个通用函数回调测试类