这是我在这里的第一篇文章,我对编程特别是C还是陌生的。几周前,我开始阅读《音频编程书》(MIT出版社),并扩展了一些示例以尝试进一步理解事物。
我认为我的问题在于我如何尝试将数据(在初始化函数中从用户检索到)传递给PortAudio回调。我觉得我所做的与示例(书中和PortAudio的示例,例如paex_sine.c)没有什么不同,但是由于某些原因,我的代码无法正常工作,我一直在努力工作试图理解为什么靠在墙上。我已经尝试过广泛地搜索解决方案或示例代码以进行研究,但是我有点不知道我不知道什么,因此返回的并不多。
如何使用户数据进入回调?
我是不是只是不了解指针和结构如何工作,并试图迫使它们去做自己不想做的事情?
还是我只是忽略了一些明显的东西?
下面的代码给出了很高的音调输出,较短的高音调尖音或无(可听)输出:
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define FRAME_BLOCK_LEN 64
#define SAMPLING_RATE 44100
#define TWO_PI (3.14159265f * 2.0f)
PaStream *audioStream;
double si = 0;
typedef struct
{
float frequency;
float phase;
}
paTestData;
int audio_callback (const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeinfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned long i;
// data->frequency = 400;
for(i = 0; i < framesPerBuffer; i++){
si = TWO_PI * data->frequency / SAMPLING_RATE; // calculate sampling-incr
*out++ = sin(data->phase);
*out++ = sin(data->phase);
data->phase += si; // add sampling-incr to phase
}
return paContinue;
}
void init_stuff()
{
float frequency;
int i;
PaStreamParameters outputParameters;
paTestData data;
printf("type the modulator frequency in Hz: ");
scanf("%f", &data.frequency); // get modulator frequency
printf("you chose data.frequency %.2f\n",data.frequency);
data.phase = 0.0;
printf("initializing Portaudio. Please wait...\n");
Pa_Initialize(); // initialize Portaudio
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
Pa_OpenStream( // open paStream object
&audioStream, // portaudio stream object
NULL, // input params
&outputParameters, // output params
SAMPLING_RATE, // SampleRate
FRAME_BLOCK_LEN, // frames per buffer
paNoFlag, // set no Flag
audio_callback, // callbak function address
&data ); // user data
Pa_StartStream(audioStream); // start the callback mechanism
printf("running... press space bar and enter to exit\n");
}
void terminate_stuff()
{
Pa_StopStream(audioStream); // stop callback mechanism
Pa_CloseStream(audioStream); // destroy audio stream object
Pa_Terminate(); // terminate portaudio
}
int main(void)
{
init_stuff();
while(getchar() != ' ') Pa_Sleep(100);
terminate_stuff();
return 0;
}
取消注释
data->frequency = 400;
至少会播放400hz正弦波,但这会忽略在init_stuff()
中完成的任何用户输入如果我在回调中放入
printf("%f\n",data->frequency);
,它将输出0.000000或-146730090609497866240.000000之类的内容。这是非常不可预测的,这确实使我认为它与指针相关。
我编写此代码的目标是最终合并包络发生器以改变音高,并可能合并波表振荡器,因此我不会为每次迭代计算sin(x)。
我可以使用书中使用的类似portf的阻塞API来使信封和波形表正常工作,但是尝试改编早期章节中的任何代码以使用PortAudio回调,这让我不禁思索。
非常感谢!
最佳答案
您的回调数据存在的问题是,它超出了范围,并且一旦init_stuff
完成执行,内存便被释放。
您应该使用malloc
或new
为回调数据分配内存,并将指针传递给回调。
例如:
void init_stuff()
{
float frequency;
int i;
PaStreamParameters outputParameters;
paTestData *data = (paTestData *) malloc(sizeof(paTestData));
printf("type the modulator frequency in Hz: ");
scanf("%f", &(data->frequency)); // get modulator frequency
printf("you chose data.frequency %.2f\n",data->frequency);
data->phase = 0.0;
...
Pa_OpenStream( // open paStream object
&audioStream, // portaudio stream object
NULL, // input params
&outputParameters, // output params
SAMPLING_RATE, // SampleRate
FRAME_BLOCK_LEN, // frames per buffer
paNoFlag, // set no Flag
audio_callback, // callbak function address
data );
...
关于c - 对将用户数据传递到PortAudio回调感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60458785/