简体   繁体   中英

How to capture audio output in iOS?

I'm playing an audio stream from the internet in my app, and I would like to display a graphic equalizer. The library that I'm using for the streaming is FreeStreamer . For drawing the graphic equalizer I'm using ZLHistogramAudioPlot . These two libraries are the only ones that fit my needs. The problem is I can't get them to work together.

The ZLHistogramAudioPlot requires a buffer and bufferSize in order to update it's view. Here is it's update method:

- (void)updateBuffer:(float *)buffer withBufferSize:(UInt32)bufferSize {
    [self setSampleData:buffer length:bufferSize];
}

Unfortunately, the FreeStreamer library doesn't provide a method to read the audiot output as it goes out towards the sound card. So, what I need is a way to read the audio output stream that's about to play through the speakers (not the byte stream from the internet, because that's received in chunks, and then buffered, which means that the histogram won't be in real-time).

I've discovered that AURemoteIO from Apple's CoreAudio framework can be used to do this, but Apple's sample project is complex beyond understanding, and there are very little to none examples online about using AURemoteIO .

Is this the best way to achieve this, and if so, any helpful info/links would be greatly appreciated.

Here is a possible answer from looking through the FreeStreamer headers

#define minForSpectrum 1024

@implementation MyClass {
    TPCircularBuffer SpectrumAnalyzerBuffer;
}

- (void)dealloc {
    TPCircularBufferCleanup(&SpectrumAnalyzerBuffer);
}

-(instancetype) init {
   self = [super init];
   if (self) {
      TPCircularBufferInit(&SpectrumAnalyzerBuffer, 16384);
      self.audioController.activeStream.delegate = self;
   }
   return self;
}

- (void)audioStream:(FSAudioStream *)audioStream samplesAvailable:(const int16_t *)samples count:(NSUInteger)count {
    // incoming data is integer

    SInt16 *buffer = samples;
    Float32 *floatBuffer = malloc(sizeof(Float32)*count);
    // convert to float
    vDSP_vflt16(buffer, 1, floatBuffer, 1, count);

    // scale
    static float scale = 1.f / (INT16_MAX/2);
    static float zero = 0.f;

    vDSP_vsmsa(floatBuffer, 1, &scale, &zero, floatBuffer, 1, count);

    TPCircularBufferProduceBytes(&SpectrumAnalyzerBuffer, floatBuffer, count*sizeof(Float32));

    free(floatBuffer);   
}

- (void) timerCallback: (NSTimer*) timer {

    Float32 *spectrumBufferData = TPCircularBufferTail(&SpectrumAnalyzerBuffer, &availableSpectrum);

    if (availableSpectrum >= minForSpectrum) {
        // note visualiser may want chunks of a fixed size if its doing fft
        [histogram updateBuffer: spectrumBufferData length: minForSpectrum];
        TPCircularBufferConsume(&SpectrumAnalyzerBuffer, minForSpectrum);
    }


}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM