c – 使用PortAudio输入音频

c – 使用PortAudio输入音频,第1张

概述我试图让 flite speech synthesis library在我的Mac上工作,但是我的声音架构在flite库中不受支持.要解决这个问题,我使用 PortAudio播放合成音频;所以我不得不在audio.c文件中进行一些黑客攻击以获得使用该库的空白.我设法在GNU AutoTools处理一段时间之后,将所有的编译都很好,然后我运行该程序并得到这个输出: $./flite -t "test 我试图让 flite speech synthesis library在我的Mac上工作,但是我的声音架构在flite库中不受支持.要解决这个问题,我使用 PortAudio播放合成音频;所以我不得不在audio.c文件中进行一些黑客攻击以获得使用该库的空白.我设法在GNU autoTools处理一段时间之后,将所有的编译都很好,然后我运行该程序并得到这个输出:
$./flite -t "test"frameIndex: 0maxFrameIndex: 0numChannels: 1numSamples: 7225sampleRate: 8000=== Now playing back. ===Waiting for playback to finish.frameIndex in callback: -2008986336maxFrameIndex in callback: 32655numChannels in callback: 152579008numSamples in callback: 0sampleRate in callback: 0Segmentation fault: 11  $./flite -t "test"frameIndex: 0maxFrameIndex: 0numChannels: 1numSamples: 7225sampleRate: 8000=== Now playing back. ===Waiting for playback to finish.frameIndex in callback: -71217888maxFrameIndex in callback: 32712numChannels in callback: 232979392numSamples in callback: 0sampleRate in callback: 0Segmentation fault: 11

这是audio.c文件中的相关代码,当我提供命令行参数-t时调用它.在进行了一些调试之后,我在playCallback()函数中标记了分段故障发生的兴趣区域.

static int playCallback( const voID *inputBuffer,voID *outputBuffer,unsigned long framesPerBuffer,const PaStreamCallbackTimeInfo* timeInfo,PaStreamCallbackFlags statusFlags,voID *userData ){    cst_wave *data = (cst_wave*)userData;    short *rptr = &data->samples[data->frameIndex * data->num_channels];    short *wptr = (short*)outputBuffer;    unsigned int i;    int finished;    unsigned int framesleft = cst_wave_maxFrameIndex(data) - cst_wave_frameIndex(data);    (voID) inputBuffer; /* Prevent unused variable warnings. */    (voID) timeInfo;    (voID) statusFlags;    (voID) userData;    printf("frameIndex in callback: %d\n",cst_wave_frameIndex(data));    printf("maxFrameIndex in callback: %d\n",cst_wave_maxFrameIndex(data));    printf("numChannels in callback: %d\n",cst_wave_num_channels(data));    printf("numSamples in callback: %d\n",cst_wave_num_samples(data));    printf("sampleRate in callback: %d\n\n",cst_wave_sample_rate(data));    if( framesleft < framesPerBuffer )    {        /* final buffer... */        for( i=0; i<framesleft; i++ )        {            *wptr++ = *rptr++;  /* left */            if( cst_wave_num_channels(data) == 2 ) *wptr++ = *rptr++;  /* right */        }        for( ; i<framesPerBuffer; i++ )        {            *wptr++ = 0;  /* left */            if( cst_wave_num_channels(data) == 2) *wptr++ = 0;  /* right */        }        data->frameIndex += framesleft;        finished = paComplete;    }    else    {        for( i=0; i<framesPerBuffer; i++ )        {            *wptr++ = *rptr++;  /* left */            if( cst_wave_num_channels(data) == 2 ) *wptr++ = *rptr++;  /* right */        }        cst_wave_set_frameIndex(data,framesPerBuffer);        finished = paContinue;    }    return finished;}int play_wave(cst_wave *w){    PaStream* stream;    PaStreamParameters outputParameters;    cst_wave_set_frameIndex(w,0);    cst_wave_set_maxFrameIndex(w,(cst_wave_num_samples(w) / cst_wave_sample_rate(w)) * cst_wave_num_channels(w) * sizeof(short));    int err = 0;    err = Pa_Initialize();    outputParameters.device = Pa_GetDefaultOutputDevice();    if (outputParameters.device == paNoDevice)    {        fprintf(stderr,"Error: No default output device.\n");        return -5;    }    printf("frameIndex: %d\n",cst_wave_frameIndex(w));    printf("maxFrameIndex: %d\n",cst_wave_maxFrameIndex(w));    printf("numChannels: %d\n",cst_wave_num_channels(w));    printf("numSamples: %d\n",cst_wave_num_samples(w));    printf("sampleRate: %d\n",cst_wave_sample_rate(w));    outputParameters.channelCount = cst_wave_num_channels(w);    outputParameters.sampleFormat = paInt16;    outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;    outputParameters.hostAPISpecificStreamInfo = NulL;    puts("=== Now playing back. ===");    err = Pa_OpenStream(&stream,NulL,/* no input */                        &outputParameters,cst_wave_sample_rate(w),512,paClipOff,playCallback,&w);    if( stream )    {        err = Pa_StartStream( stream );        if( err != paNoError ) goto done;        puts("Waiting for playback to finish.");        while((err = Pa_IsstreamActive(stream)) == 1) Pa_Sleep(100);        if( err < 0 ) goto done;        err = Pa_CloseStream( stream );        if( err != paNoError ) goto done;        puts("Done.");    }done:    Pa_Terminate();    free(cst_wave_samples(w));}

因为它是相关的,我还稍微修改cst_wave.h中的cst_wave结构,以便它包含我必须存储的数据,以及添加一些已经存在的#define:

typedef struct  cst_wave_struct {    const char *type;    int frameIndex;    int maxFrameIndex;    int sample_rate;    int num_samples;    int num_channels;    short *samples;} cst_wave;#define cst_wave_num_samples(w) (w?w->num_samples:0)#define cst_wave_num_channels(w) (w?w->num_channels:0)#define cst_wave_sample_rate(w) (w?w->sample_rate:0)#define cst_wave_samples(w) (w->samples)#define cst_wave_frameIndex(w) (w->frameIndex)#define cst_wave_maxFrameIndex(w) (w->maxFrameIndex)#define cst_wave_set_num_samples(w,s) w->num_samples=s#define cst_wave_set_num_channels(w,s) w->num_channels=s#define cst_wave_set_sample_rate(w,s) w->sample_rate=s#define cst_wave_set_frameIndex(w,s) w->frameIndex=s#define cst_wave_set_maxFrameIndex(w,s) w->maxFrameIndex=s

更新1:

按照@Rohan的建议,现在给我这个输出:

$./bin/flite -t "test"frameIndex: 0maxFrameIndex: 0numChannels: 1numSamples: 7225sampleRate: 8000=== Now playing back. ===Waiting for playback to finish.frameIndex in callback: 0maxFrameIndex in callback: 0numChannels in callback: 1numSamples in callback: 7225sampleRate in callback: 8000Done.flite(68929,0x7fff71c0d310) malloc: *** error for object 0x7fd6e2809800: pointer being freed was not allocated*** set a breakpoint in malloc_error_break to deBUGAbort trap: 6

为了解决这个问题,我删除了free(cst_wave_samples(w));.现在程序执行正常,没有可见的错误,但我的Mac上仍然没有音频输出.有什么建议么?

解决方法 你运气好我可以在自己的Mac上编译PortAudio和flite,并解决你的问题.

除了之前提到的以外,您还有以下几个问题,我在下面的代码转储中已经解决了所有这些问题.

>次要:你不会一直使用你自己的cst_wave API.
>次要的:我喜欢把我的时间,如果块总是包含{}.这有一个防止神秘错误的习惯.
>最大帧被设置为零.这是因为在(cst_wave_num_samples(w)/ cst_wave_sample_rate(w))* cst_wave_num_channels(w)* sizeof(short)中,您除以采样率,大于您的采样数.假定整数除法是左关联的并截断,yadda yadda yadda为零.
>最大帧仍然是错误的,因为帧包括所有通道样本.因此,帧的数量对于信道的数量和样本本身的大小是不可知的.允许自己猜测,flite将样本误认为是帧,您的最大帧索引只是cst_wave_num_samples(w).否则它将是cst_wave_num_samples(w)/ cst_wave_num_channels(w).
> PortAudio的文档指出,在流变为无效后,您应该调用Pa_StopStream(流),无论您是否等待,直到它变得如此.
>我简化了回调,并对其进行了更正

>次要:一致使用您的API
> MAJOR:Ehm … cst_wave_set_frameIndex(data,framesPerBuffer);肯定是错的你固定在帧索引512而不是递增!这是因为您打开流时要求每个缓冲区512帧,而不是通过framePerBuffer递增帧索引,您将帧索引设置为framesPerBuffer.你没有这么做,因为你的maxFrameIndex是0,所以你退出.我修改它,以便帧索引增加 – 当然你的API.

这是代码,我采取了文件和清洁的自由,直到它接近我的优雅标准.请享用!

#include <stdio.h>#include <string.h>/** * Audio play callback. *  * Follows the PaStreamCallback signature,wherein: *  * @param input   and * @param output  are either arrays of interleaved samples or; if *                non-interleaved samples were requested using the *                paNonInterleaved sample format flag,an array of buffer *                pointers,one non-interleaved buffer for each channel. * @param frameCount    The number of sample frames to be processed by the *                      stream callback. * @param timeInfo      Timestamps indicating the ADC capture time of the first *                      sample in the input buffer,the DAC output time of the *                      first sample in the output buffer and the time the *                      callback was invoked. See PaStreamCallbackTimeInfo and *                      Pa_GetStreamTime() * @param statusFlags   Flags indicating whether input and/or output buffers *                      have been inserted or will be dropped to overcome *                      underflow or overflow conditions. * @param userData      The value of a user supplIEd pointer passed to *                      Pa_OpenStream() intended for storing synthesis data *                      etc. */static int  playCallback(const voID*                     inputBuffer,voID*                           outputBuffer,unsigned long                   framesPerBuffer,PaStreamCallbackFlags           statusFlags,voID*                           userData){    (voID) inputBuffer; /* Prevent unused variable warnings. */    (voID) timeInfo;    (voID) statusFlags;    (voID) userData;    /**     * Compute current processing state.     */    cst_wave*    data;    short*       rptr;    short*       wptr;    unsigned int framesleft,/* Number of frames of data remaining within the stream ***as a whole*** */                 frames,/* Number of frames of data to be written for this buffer. */                 framesPad,/* Number of frames of padding required within the final buffer. */                 samples,/* Number of samples of data to be written for this buffer. */                 samplesPad,/* Number of samples of padding required within the final buffer. */                 numBytes,/* Number of bytes of data to be written for this buffer. */                 numBytesPad;/* Number of bytes of padding required within the final buffer. */    int          finalBuffer;/* Stores whether or not this is the final buffer. */    data         = (cst_wave*)userData;    rptr         = &data->samples[cst_wave_frameIndex  (data) *                                  cst_wave_num_channels(data)];    wptr         = (short*)outputBuffer;    framesleft   = cst_wave_maxFrameIndex(data) - cst_wave_frameIndex(data);    finalBuffer  = framesleft      <= framesPerBuffer;    frames       = finalBuffer     ?  framesleft     : framesPerBuffer;    framesPad    = framesPerBuffer -  frames;    samples      = frames     * cst_wave_num_channels(data);    samplesPad   = framesPad  * cst_wave_num_channels(data);    numBytes     = samples    * sizeof(short);    numBytesPad  = samplesPad * sizeof(short);    /**     * DeBUG code. Comment out in production.     */    printf("framesleft in callback: %u\n",framesleft);    printf("framesPerBuffer in callback: %lu\n",framesPerBuffer);    printf("frames in callback: %u\n",frames);    printf("frameIndex in callback: %d\n",cst_wave_sample_rate(data));    /**     * Output data. We handle the final buffer specially,padding it with zeros.     */    memcpy(wptr,rptr,numBytes);    wptr += samples;    rptr += samples;    cst_wave_set_frameIndex(data,cst_wave_frameIndex(data) + frames);    memset(wptr,numBytesPad);    wptr += samplesPad;    rptr += samplesPad;    /**     * Return a completion or continue code depending on whether this was the     * final buffer or not respectively.     */    return finalBuffer ? paComplete : paContinue;}/** * Play wave function. *  * Plays the given cst_wave data as audio,blocking until this is done. */int play_wave(cst_wave *w){    PaStream*          stream;    PaStreamParameters outputParameters;    int                err;    /**     * Initialize custom fIElds in cst_wave struct.     */    cst_wave_set_frameIndex(w,(cst_wave_num_samples(w)));    // / cst_wave_sample_rate(w)  * cst_wave_num_channels(w) * sizeof(short)    /**     * Initialize Port Audio device and stream parameters.     */    err = Pa_Initialize();    outputParameters.device = Pa_GetDefaultOutputDevice();    if (outputParameters.device == paNoDevice){        fprintf(stderr,"Error: No default output device.\n");        return -5;    }    printf("frameIndex: %d\n",cst_wave_sample_rate(w));    outputParameters.channelCount = cst_wave_num_channels(w);    outputParameters.sampleFormat = paInt16;    outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;    outputParameters.hostAPISpecificStreamInfo = NulL;    /**     * Open the stream for playback.     */    puts("=== Now playing back. ===");    err = Pa_OpenStream(&stream,w);    if(stream){        /**         * Start the stream.         */        err = Pa_StartStream(stream);        if(err != paNoError){            goto done;        }        /**         * Block while it plays.         */        puts("Waiting for playback to finish.");        while((err = Pa_IsstreamActive(stream)) == 1){            Pa_Sleep(100);        }        if(err < 0){            goto done;        }        /**         * Stop and close the stream. Both are necessary.         */        Pa_StopStream(stream);        err = Pa_CloseStream(stream);        if(err != paNoError){            goto done;        }        puts("Done.");    }    /**     * Terminate and leave.     */done:    Pa_Terminate();    return 0;}
总结

以上是内存溢出为你收集整理的c – 使用PortAudio输入音频全部内容,希望文章能够帮你解决c – 使用PortAudio输入音频所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1253466.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存