Get-Hip/GetHip/AudioStreamer/Classes/TDAudioFileStream.m

113 lines
4.4 KiB
Objective-C
Executable File

//
// TDAudioFileStream.m
// TDAudioStreamer
//
// Created by Tony DiPasquale on 10/4/13.
// Copyright (c) 2013 Tony DiPasquale. The MIT License (MIT).
//
#import "TDAudioFileStream.h"
@interface TDAudioFileStream ()
@property (assign, nonatomic) AudioFileStreamID audioFileStreamID;
- (void)didChangeProperty:(AudioFileStreamPropertyID)propertyID flags:(UInt32 *)flags;
- (void)didReceivePackets:(const void *)packets packetDescriptions:(AudioStreamPacketDescription *)packetDescriptions numberOfPackets:(UInt32)numberOfPackets numberOfBytes:(UInt32)numberOfBytes;
@end
void TDAudioFileStreamPropertyListener(void *inClientData, AudioFileStreamID inAudioFileStreamID, AudioFileStreamPropertyID inPropertyID, UInt32 *ioFlags)
{
TDAudioFileStream *audioFileStream = (__bridge TDAudioFileStream *)inClientData;
[audioFileStream didChangeProperty:inPropertyID flags:ioFlags];
}
void TDAudioFileStreamPacketsListener(void *inClientData, UInt32 inNumberBytes, UInt32 inNumberPackets, const void *inInputData, AudioStreamPacketDescription *inPacketDescriptions)
{
TDAudioFileStream *audioFileStream = (__bridge TDAudioFileStream *)inClientData;
[audioFileStream didReceivePackets:inInputData packetDescriptions:inPacketDescriptions numberOfPackets:inNumberPackets numberOfBytes:inNumberBytes];
}
@implementation TDAudioFileStream
- (instancetype)init
{
self = [super init];
if (!self) return nil;
OSStatus err = AudioFileStreamOpen((__bridge void *)self, TDAudioFileStreamPropertyListener, TDAudioFileStreamPacketsListener, 0, &_audioFileStreamID);
if (err) return nil;
self.discontinuous = YES;
return self;
}
- (void)didChangeProperty:(AudioFileStreamPropertyID)propertyID flags:(UInt32 *)flags
{
if (propertyID == kAudioFileStreamProperty_ReadyToProducePackets) {
UInt32 basicDescriptionSize = sizeof(self.basicDescription);
OSStatus err = AudioFileStreamGetProperty(self.audioFileStreamID, kAudioFileStreamProperty_DataFormat, &basicDescriptionSize, &_basicDescription);
if (err) return [self.delegate audioFileStream:self didReceiveError:err];
UInt32 byteCountSize;
AudioFileStreamGetProperty(self.audioFileStreamID, kAudioFileStreamProperty_AudioDataByteCount, &byteCountSize, &_totalByteCount);
UInt32 sizeOfUInt32 = sizeof(UInt32);
err = AudioFileStreamGetProperty(self.audioFileStreamID, kAudioFileStreamProperty_PacketSizeUpperBound, &sizeOfUInt32, &_packetBufferSize);
if (err || !self.packetBufferSize) {
AudioFileStreamGetProperty(self.audioFileStreamID, kAudioFileStreamProperty_MaximumPacketSize, &sizeOfUInt32, &_packetBufferSize);
}
Boolean writeable;
err = AudioFileStreamGetPropertyInfo(self.audioFileStreamID, kAudioFileStreamProperty_MagicCookieData, &_magicCookieLength, &writeable);
if (!err) {
self.magicCookieData = calloc(1, self.magicCookieLength);
AudioFileStreamGetProperty(self.audioFileStreamID, kAudioFileStreamProperty_MagicCookieData, &_magicCookieLength, self.magicCookieData);
}
[self.delegate audioFileStreamDidBecomeReady:self];
}
}
- (void)didReceivePackets:(const void *)packets packetDescriptions:(AudioStreamPacketDescription *)packetDescriptions numberOfPackets:(UInt32)numberOfPackets numberOfBytes:(UInt32)numberOfBytes
{
if (packetDescriptions) {
for (NSUInteger i = 0; i < numberOfPackets; i++) {
SInt64 packetOffset = packetDescriptions[i].mStartOffset;
UInt32 packetSize = packetDescriptions[i].mDataByteSize;
[self.delegate audioFileStream:self didReceiveData:(const void *)(packets + packetOffset) length:packetSize packetDescription:(AudioStreamPacketDescription)packetDescriptions[i]];
}
} else {
[self.delegate audioFileStream:self didReceiveData:(const void *)packets length:numberOfBytes];
}
}
- (void)parseData:(const void *)data length:(UInt32)length
{
OSStatus err;
if (self.discontinuous) {
err = AudioFileStreamParseBytes(self.audioFileStreamID, length, data, kAudioFileStreamParseFlag_Discontinuity);
self.discontinuous = NO;
} else {
err = AudioFileStreamParseBytes(self.audioFileStreamID, length, data, 0);
}
if (err) [self.delegate audioFileStream:self didReceiveError:err];
}
- (void)dealloc
{
AudioFileStreamClose(self.audioFileStreamID);
free(_magicCookieData);
}
@end