Search code examples
iphoneiosipadaudiosampling

iOS How to get audio samples from song (ipod library)?


Currently in my app, I'm doing FFT analyse on audio samples coming from built-in microphone. I let user play song from ipod library, using speakers, microphone capture the sound and I can calculate FFT. I'm not happy with this solution. I would like to get samples directly from audio file (ipod library) and calculate FFT. I know this is possible, because I saw apps in AppStore, which can analyse song from ipod library. How can I do that?


Solution

  • I ended up using novocaine. Calculating FFT with it, is simple as that:

    self.audioManager = [Novocaine audioManager];
    self.audioManager.forceOutputToSpeaker = YES;
    
    self.fileReader= [[AudioFileReader alloc]
                       initWithAudioFileURL:inputFileURL
                       samplingRate:self.audioManager.samplingRate
                       numChannels:self.audioManager.numOutputChannels];
    
    
    [self.fileReader play];
    
    __block COMPLEX_SPLIT AA = A;
    __block int nOver = nOver2;
    FFTSetup fftSetup2 = fftSetup;
    __block int log = log2n;
    __block int n2 = n;
    __weak MainViewController *listener2 = listener;
    __weak AudioManager *wself = self;
    __block float *window = (float *)malloc(sizeof(float) * n2);
    vDSP_hamm_window(window, n2, 0);
    __block BOOL songStarted = NO;
    __block float *data = (float *)malloc(sizeof(float) * n2);
    [self.audioManager setOutputBlock:^(float *data2, UInt32 numFrames, UInt32 numChannels)
     {
         [wself.fileReader retrieveFreshAudio:data2 numFrames:numFrames numChannels:numChannels];
         if(!wself.fileReader.playing && songStarted)
         {
             [listener2 nextSong:nil];
             [wself.audioManager setOutputBlock:nil];
             return;
         }
         else if(wself.fileReader.playing && !songStarted)
             songStarted = YES;
    
    
         vDSP_vmul(data2, 1, window, 1, data, 1, n2);
         vDSP_ctoz((COMPLEX*)data, 2, &AA, 1, nOver);
         vDSP_fft_zrip(fftSetup2, &AA, 1, log, FFT_FORWARD);
         // calculating square of magnitude for each value
         vDSP_zvmags(&AA, 1, AA.realp, 1, nOver);
    
         float *tab_results = (float *)malloc(32 * sizeof(float));
         for(int i=0;i<32;i++)
             tab_results[i]=AA.realp[i+5];//i+5
         [listener2 sendResults:tab_results];
         memset(data, 0, n2*sizeof(float));
     }];
    
    [self.audioManager play];