gpt4 book ai didi

c - 使用 PortAudio 写入不正确数量的帧?

转载 作者:太空宇宙 更新时间:2023-11-03 23:27:36 25 4
gpt4 key购买 nike

运行我的程序,我似乎没有根据索引写入正确数量的帧。

$ ./test
Now recording!! Please speak into the microphone.
index = 0
Writing to: test.flac

audio.h:

#include <stdint.h>
#include <string.h>

typedef struct
{
uint32_t duration;
uint16_t format_type;
uint16_t number_of_channels;
uint32_t sample_rate;
uint32_t frameIndex; /* Index into sample array. */
uint32_t maxFrameIndex;
char* recordedSamples;
} AudioData;

int recordFLAC(AudioData* data, const char *fileName);
AudioData* initAudioData(uint32_t sample_rate, uint16_t channels, uint32_t duration);

capture.c:

#include <stdio.h>
#include <stdlib.h>
#include <portaudio.h>
#include <sndfile.h>
#include "audio.h"

AudioData* initAudioData(uint32_t sample_rate, uint16_t channels, uint32_t duration)
{
AudioData* data = malloc(sizeof(*data));
if (!data) return NULL;
data->duration = duration;
data->format_type = 1;
data->number_of_channels = channels;
data->sample_rate = sample_rate;
data->frameIndex = 0;
data->maxFrameIndex = sample_rate * duration;
data->recordedSamples = malloc(sizeof(data->maxFrameIndex));
if(!data->maxFrameIndex) return NULL;
return data;
}

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

(void) outputBuffer;
(void) timeInfo;
(void) statusFlags;

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){
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 recordFLAC(AudioData* data, const char *fileName)
{
PaStreamParameters inputParameters;
PaStream* stream;
int err = 0;
int totalFrames = data->maxFrameIndex;
int numSamples;
int numBytes;
char max, val;
double average;

numSamples = totalFrames * data->number_of_channels;
numBytes = numSamples;
data->recordedSamples = malloc(numBytes);
if(!data->recordedSamples)
{
printf("Could not allocate record array.\n");
goto done;
}
for(int i = 0; i < numSamples; i++) data->recordedSamples[i] = 0;

if((err = Pa_Initialize())) goto done;

inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
if (inputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default input device.\n");
goto done;
}
inputParameters.channelCount = data->number_of_channels; /* stereo input */
inputParameters.sampleFormat = data->format_type;
inputParameters.suggestedLatency = Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency;
inputParameters.hostApiSpecificStreamInfo = NULL;

/* Record some audio. -------------------------------------------- */
err = Pa_OpenStream(&stream, &inputParameters, NULL, data->sample_rate, paFramesPerBufferUnspecified, paClipOff, recordCallback, &data);
if(err) goto done;
if((err = Pa_StartStream(stream))) goto done;
puts("Now recording!! Please speak into the microphone.");

while((err = Pa_IsStreamActive(stream)) == 1)
{
Pa_Sleep(1000);
printf("index = %d\n", data->frameIndex);
}
if( err < 0 ) goto done;

err = Pa_CloseStream(stream);
if(err) goto done;

/* Measure maximum peak amplitude. */
max = 0;
average = 0.0;
for(int i = 0; i < numSamples; i++)
{
val = data->recordedSamples[i];
val = abs(val);
if( val > max )
{
max = val;
}
average += val;
}

average /= (double)numSamples;

done:
Pa_Terminate();
if(err)
{
fprintf(stderr, "An error occured while using the portaudio stream\n");
fprintf(stderr, "Error number: %d\n", err);
fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err));
err = 1; /* Always return 0 or 1, but no other return codes. */
}
else
{
SF_INFO sfinfo;
sfinfo.channels = 1;
sfinfo.samplerate = data->sample_rate;
sfinfo.format = SF_FORMAT_FLAC | SF_FORMAT_PCM_16;

// open to file
printf("Writing to: %s\n", fileName);
SNDFILE * outfile = sf_open(fileName, SFM_WRITE, &sfinfo);
if (!outfile) return -1;

// prepare a 3 second long buffer (sine wave)
const int size = data->sample_rate * 3;

// write the entire buffer to the file
sf_write_raw(outfile, data->recordedSamples, size);

// force write to disk
sf_write_sync(outfile);
// don't forget to close the file
sf_close(outfile);
}
return err;
}

我不太确定我哪里出错了,我知道我需要写更多的框架。有什么建议吗?

最佳答案

您对示例格式的假设似乎有问题。在回调中,您使用 char *(单字节)作为样本格式,但在您的 libsndfile 调用中,您使用 SF_FORMAT_PCM_16 打开一个 16 位文件。

这不是很好:

data->format_type = 1;

我建议使用 PortAudio 库中的符号常量之一进行示例格式化。也许你想要一个 16 位的?如果是这样,您希望在 PA 回调中使用 short* 而不是 char*

最后,如果您的 channel 数不是 1,则复制循环不正确:

    for(i = 0; i < framesToCalc; i++){
*index_ptr++ = 0;
}

“帧”包含所有 channel 的数据,例如,如果它是立体声输入,您的迭代需要像这样处理左右 channel :

    for(i = 0; i < framesToCalc; i++){
*index_ptr++ = 0; // left
*index_ptr++ = 0; // right
}

其他循环也一样。

关于c - 使用 PortAudio 写入不正确数量的帧?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23116333/

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