1

我正在我的应用程序中播放来自互联网的音频流,并且我想显示一个图形均衡器。我用于流式传输的库是FreeStreamer. 为了绘制我正在使用的图形均衡器ZLHistogramAudioPlot。这两个库是唯一符合我需求的库。问题是我不能让他们一起工作。

ZLHistogramAudioPlot需要一个缓冲区和缓冲区大小才能更新它的视图。这是它的更新方法:

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

不幸的是,该FreeStreamer库没有提供一种方法来读取音频输出,因为它向声卡输出。所以,我需要的是一种读取即将通过扬声器播放的音频输出流的方法(而不是来自互联网的字节流,因为它是以块的形式接收的,然后被缓冲,这意味着直方图不会在即时的)。

我发现可以使用AURemoteIOApple 的CoreAudio框架来做到这一点,但是 Apple 的示例项目复杂到无法理解,网上关于使用AURemoteIO.

这是实现这一目标的最佳方式吗?如果是这样,任何有用的信息/链接将不胜感激。

4

1 回答 1

1

这是查看 FreeStreamer 标头的可能答案

#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);
    }


}
于 2015-05-21T09:59:20.303 回答