gpt4 book ai didi

在 PortAudio 中连续录音(来自麦克风或输出)

转载 作者:太空狗 更新时间:2023-10-29 17:23:47 24 4
gpt4 key购买 nike

我正在尝试在 PortAudio 中创建一个音乐可视化应用程序,我做了一些基础研究并找到了一些关于如何从麦克风录制到(临时)文件的示例。但是没有在记录期间不使用运行时数据的示例。

那么我怎样才能开始一个连续的音频流,在那里我可以从当前“帧”中捕获数据?

我是这样尝试的:

#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>

#include "portaudio.h"

#define SAMPLE_RATE (44100)

typedef struct{
int frameIndex;
int maxFrameIndex;
char* recordedSamples;
}
testData;

PaStream* stream;

static int recordCallback(const void* inputBuffer, void* outputBuffer, unsigned long frameCount, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void* userData){
testData* data = (testData*)userData;
const char* buffer_ptr = (const char*)inputBuffer;
char* index_ptr = &data->recordedSamples[data->frameIndex];

long framesToCalc;
long i;
int finished;
unsigned long framesLeft = data->maxFrameIndex - data->frameIndex;

if(framesLeft < frameCount){
framesToCalc = framesLeft;
finished = paComplete;
}else{
framesToCalc = frameCount;
finished = paContinue;
}

if(inputBuffer == NULL){
for(i = 0; i < framesToCalc; i++){
*index_ptr++ = 0;
}
}else{
for(i = 0; i < framesToCalc; i++){
*index_ptr++ = *buffer_ptr++;
}
}

data->frameIndex += framesToCalc;
return finished;
}

int setup(testData streamData){
PaError err;

err = Pa_Initialize();
if(err != paNoError){
fprintf(stderr, "Pa_Initialize error: %s\n", Pa_GetErrorText(err));
return 1;
}

PaStreamParameters inputParameters;
inputParameters.device = Pa_GetDefaultInputDevice();
if (inputParameters.device == paNoDevice) {
fprintf(stderr, "Error: No default input device.\n");
return 1;
}

inputParameters.channelCount = 1;
inputParameters.sampleFormat = paInt8;
inputParameters.suggestedLatency = Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency;
inputParameters.hostApiSpecificStreamInfo = NULL;

err = Pa_OpenStream(&stream, &inputParameters, NULL, SAMPLE_RATE, 256, paClipOff, recordCallback, &streamData);
if(err != paNoError){
fprintf(stderr, "Pa_OpenDefaultStream error: %s\n", Pa_GetErrorText(err));
return 1;
}

err = Pa_StartStream(stream);
if(err != paNoError){
fprintf(stderr, "Pa_StartStream error: %s\n", Pa_GetErrorText(err));
return 1;
}

return 0;
}

void quit(testData streamData){
PaError err;
err = Pa_Terminate();
if(err != paNoError){
fprintf(stderr, "Pa_Terminate error: %s\n", Pa_GetErrorText(err));
}

if(streamData.recordedSamples)
free(streamData.recordedSamples);
}

int main(){
int i;
PaError err;
testData streamData = {0};

streamData.frameIndex = 0;
streamData.maxFrameIndex = SAMPLE_RATE;
streamData.recordedSamples = (char*)malloc(SAMPLE_RATE * sizeof(char));
if(streamData.recordedSamples == NULL)
printf("Could not allocate record array.\n");

for(i=0; i<SAMPLE_RATE; i++)
streamData.recordedSamples[i] = 0;

//int totalFrames = SAMPLE_RATE;

if(!setup(streamData)){
printf("Opened\n");

int i = 0;

while(i++ < 500){

if((err = Pa_GetStreamReadAvailable(stream)) != paNoError)
break;

while((err = Pa_IsStreamActive(stream)) == 1){
Pa_Sleep(1000);
}

err = Pa_CloseStream(stream);
if(err != paNoError)
break;

streamData.frameIndex = 0;
for(i=0; i<SAMPLE_RATE; i++)
streamData.recordedSamples[i] = 0;
}

if(err != paNoError){
fprintf(stderr, "Active stream error: %s\n", Pa_GetErrorText(err));
}

quit(streamData);
}else{
puts("Couldn't open\n");
}
return 0;
}

但它给出了以下输出:

ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
ALSA lib pcm_dmix.c:957:(snd_pcm_dmix_open) The dmix plugin supports only playback stream
Active stream error: Can't read from a callback stream

最佳答案

更新:

这段代码的用途是什么?

        if((err = Pa_GetStreamReadAvailable(stream)) != paNoError)
break;

在我看来,这是导致您(最新)问题的原因。为什么需要检索(然后丢弃)无需等待即可从流中读取的帧数,因为流是回调流,这可能为零?


上一个答案:

这看起来非常可疑:

static void* data;
/* ... */
static int recordCallback(const void* inputBuffer, void* outputBuffer, unsigned long frameCount, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void* userData){
testData* data = (testData*)userData;
/* ... */
}

首先,为什么有两个名为data的变量?这太愚蠢了……你能想出更合适的标识符吗?

其次,您将传递一个&data(一个void **)给Pa_OpenStream。据推测,Pa_OpenStream 将相同的值传递给您的回调函数,您将指向 void * 的指针视为指向 testData *。这是未定义的行为。

删除 static void* data; 。没必要,在这里。在 main 中的最顶部声明​​一个新的 testData data = { 0 };。现在您将 testData *(转换为 void *)传递给 Pa_OpenStream,Pa_OpenStream 会将其传递给您的回调,您可以在其中安全地将其转换回 >testData * 就像你一样。您可能希望在调用 Pa_OpenStream 之前设置 data 的成员...

关于在 PortAudio 中连续录音(来自麦克风或输出),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15690668/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com