如何播放和读取.caf PCM音频文件



我有一个应用程序,它从iPod库中选择一首歌曲,然后将该歌曲作为".caf"文件复制到应用程序的目录中。我现在需要播放,同时从Accelerate框架将该文件读取到Apples FFT中,这样我就可以像频谱图一样可视化数据。这是FFT的代码:

void FFTAccelerate::doFFTReal(float samples[], float amp[], int numSamples)
{
int i;
vDSP_Length log2n = log2f(numSamples);
//Convert float array of reals samples to COMPLEX_SPLIT array A
vDSP_ctoz((COMPLEX*)samples,2,&A,1,numSamples/2);
//Perform FFT using fftSetup and A
//Results are returned in A
vDSP_fft_zrip(fftSetup, &A, 1, log2n, FFT_FORWARD);
//Convert COMPLEX_SPLIT A result to float array to be returned
amp[0] = A.realp[0]/(numSamples*2);
for(i=1;i<numSamples;i++)
    amp[i]=sqrt(A.realp[i]*A.realp[i]+A.imagp[i]*A.imagp[i])/numSamples;
}
//Constructor
FFTAccelerate::FFTAccelerate (int numSamples)
{
vDSP_Length log2n = log2f(numSamples);
fftSetup = vDSP_create_fftsetup(log2n, FFT_RADIX2);
int nOver2 = numSamples/2;
A.realp = (float *) malloc(nOver2*sizeof(float));
A.imagp = (float *) malloc(nOver2*sizeof(float));
}

我的问题是,如何在播放歌曲的同时循环播放".caf"音频文件以提供FFT?我只需要一个频道。我想我需要获得1024个歌曲样本,在FTT中处理,然后进一步向下移动文件,再获取1024个样本。但我不知道如何阅读音频文件来做到这一点。该文件的采样率为44100.0赫兹,为线性PCM格式,16位,如果有帮助的话,我相信也是交错的。。。

尝试ExtendedAudioFile API(需要AudioToolbox.framework)。

#include <AudioToolbox/ExtendedAudioFile.h>
NSURL   *urlToCAF = ...;
ExtAudioFileRef caf;
OSStatus    status;
status = ExtAudioFileOpenURL((__bridge CFURLRef)urlToCAF, &caf);
if(noErr == status) {
    // request float format
    const UInt32 NumFrames = 1024;
    const int ChannelsPerFrame = 1;  // Mono, 2 for Stereo
    // request float format
    AudioStreamBasicDescription clientFormat;
    clientFormat.mChannelsPerFrame = ChannelsPerFrame;
    clientFormat.mSampleRate = 44100;
    clientFormat.mFormatID = kAudioFormatLinearPCM;
    clientFormat.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsNonInterleaved; // float
    int cmpSize = sizeof(float);
    int frameSize = cmpSize*ChannelsPerFrame;
    clientFormat.mBitsPerChannel = cmpSize*8;
    clientFormat.mBytesPerPacket = frameSize;
    clientFormat.mFramesPerPacket = 1;
    clientFormat.mBytesPerFrame = frameSize;
    status = ExtAudioFileSetProperty(caf, kExtAudioFileProperty_ClientDataFormat, sizeof(clientFormat), &clientFormat);
     if(noErr != status) { /* handle it */ }
    while(1) {
        float   buf[ChannelsPerFrame*NumFrames];
        AudioBuffer ab = { ChannelsPerFrame, sizeof(buf), buf };
        AudioBufferList abl;
        abl.mNumberBuffers = 1;
        abl.mBuffers[0] = ab;
        UInt32  ioNumFrames = NumFrames;
        status = ExtAudioFileRead(caf, &ioNumFrames, &abl);
        if(noErr == status) {
            // process ioNumFrames here in buf
            if(0 == ioNumFrames) {
                // EOF!
                break;
            } else if(ioNumFrames < NumFrames) {
                // TODO: pad buf with zeroes out to NumFrames 
            } else {
                 float amp[NumFrames]; // scratch space
                 doFFTReal(buf, amp, NumFrames);
            }
        }
    }
    // later
    status = ExtAudioFileDispose(caf);
    if(noErr != status) { /* hmm */ }
}

相关内容

  • 没有找到相关文章

最新更新