Reputation: 707
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.
Upvotes: 2
Views: 1289
Reputation: 2522
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);
}
}
Upvotes: 1