【问题标题】:How do you perform an FFT of a WAV file on the iPhone?如何在 iPhone 上执行 WAV 文件的 FFT?
【发布时间】:2024-05-19 08:15:02
【问题描述】:

我必须在 iPhone 应用程序中对 .wav 文件执行 FFT。我已经看到了 FFT 算法,但是我将如何解析 WAV 文件并在这样的算法中使用?

我应该将 WAV 文件转换为 NSData 还是其他格式?

之前有没有人在 iPhone 中成功地对 WAV 文件进行过 FFT?我尝试为此使用iPhoneFFT,但没有成功。

例如,那里的代码说明

 // 2. Then fill up an array with data with your own function
   fillUpInputSignalWithMyData(myFFT.inputData);

我如何将 WAV 文件中的数据提供给这样的东西?

【问题讨论】:

    标签: iphone signal-processing fft


    【解决方案1】:
    MyAudioFile  *audioFile = [[MyAudioFile alloc]init];
    OSStatus result = [audioFile open:var ofType:@"wav"];
    int numFrequencies=16384;
    int kNumFFTWindows=10;
    
    OouraFFT *myFFT = [[OouraFFT alloc] initForSignalsOfLength:numFrequencies*2 andNumWindows:kNumFFTWindows];
    for(long i=0; i<myFFT.dataLength; i++)
    {
    myFFT.inputData[i] = (double)audioFile.audioData[i];
    } 
    [myFFT calculateWelchPeriodogramWithNewSignalSegment];
    for (int i=0;i<=8192;i++) {
    NSLog(@"the spectrum data %d is  %f ",i,myFFT.spectrumData[i]);
    
    }
    

    我创建了 MyAudioFile 类,其中包含

    -(OSStatus)open:(NSString *)fileName ofType:(NSString *)fileType{
    OSStatus result = -1;
    
    CFStringRef filePath=fileName;
    
    CFURLRef audioFileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (CFStringRef)filePath, kCFURLPOSIXPathStyle, false);
    //open audio file
    result = AudioFileOpenURL (audioFileURL, kAudioFileReadPermission, 0, &mAudioFile);
    if (result == noErr) {
        //get  format info
        UInt32 size = sizeof(mASBD);
    
        result = AudioFileGetProperty(mAudioFile, kAudioFilePropertyDataFormat, &size, &mASBD);
    
        UInt32 dataSize = sizeof packetCount;
        result = AudioFileGetProperty(mAudioFile, kAudioFilePropertyAudioDataPacketCount, &dataSize, &packetCount);
        NSLog([NSString stringWithFormat:@"File Opened, packet Count: %d", packetCount]);
    
        UInt32 packetsRead = packetCount;
        UInt32 numBytesRead = -1;
        if (packetCount > 0) { 
            //allocate  buffer
            audioData = (SInt16*)malloc( 2 *packetCount);
            //read the packets
            result = AudioFileReadPackets (mAudioFile, false, &numBytesRead, NULL, 0, &packetsRead,  audioData); 
            NSLog([NSString stringWithFormat:@"Read %d  bytes,  %d packets", numBytesRead, packetsRead]);
        }
    }
    else
        NSLog([NSString stringWithFormat:@"Could not open file: %@", filePath]);
    
    
    CFRelease (audioFileURL);     
    return result;
    }
    

    就是这样。我正在获取功率谱阵列。我已经检查了样本正弦波。它工作正常。

    【讨论】:

    • 勇士你好,谢谢。用你的代码我解决了我的问题,但我知道它对静态文件很有用,如果我用 TSLibraryImport 类转换该文件路径会破坏它的崩溃应用程序而不是输出。请尝试帮助我..
    • @Warrior 请问我如何使用你的类,MyAudioFile 类的类型是什么?什么是 packerCount、mAudioFile、mASBD 等。很抱歉提出这样一个令人困惑的问题。
    【解决方案2】:

    研究你的 C 数据类型。

    FFT 通常可以将数据作为几种 C 数据类型之一的 C 数组(不是 NSArray)...这包括 iOS 4 内置的 Accelerate Framework FFT。这些类型可能是一个短整数、长整数、浮点数或双精度数组。在最新的 iOS 设备上,使用短浮点数执行 FFT 通常是最快的。检查您选择的 FFT 需要哪种数据类型。许多需要实向量和虚向量作为复数输入。

    最常见的 wav 文件只有 1 个带有 44 字节标头的块,然后是作为短整数数组的原始 PCM 数据,单声道或立体声交错。只需将此数组转换为 FFT 所需的数据类型即可。对于单声道数据,这样简单的事情可能会起作用:

    for (i=0;i<n;i++) { 
        myFloatArray_RealPart[i] = wavInts[i+22]; 
        myFloatArray_ImaginaryPart[i] = 0.0; 
    }
    

    (但您需要验证您拥有的波形文件的类型以及确保所需的 FFT 参数!)

    【讨论】:

    • 请详细给出代码。我被卡住了。如何将.wav文件作为输入。
    【解决方案3】:

    嗯,根据: http://github.com/alexbw/iPhoneFFT/blob/master/OouraFFT.h

    你使用:

    double *inputData;
    

    因此,您将 fopen() wav 文件,去掉标题并获得双精度数组。

    【讨论】:

    • 我不懂c,能不能给一些打开wav文件获取double数组的代码
    最近更新 更多