Merged decoder and converter threads to facilitate midstream format changing.

CQTexperiment
vspader 2007-03-03 17:19:37 +00:00
parent 116e78c3ed
commit 1aead1bf0d
14 changed files with 217 additions and 309 deletions

View File

@ -9,13 +9,11 @@
#import <Cocoa/Cocoa.h>
#import "InputNode.h"
#import "ConverterNode.h"
#import "AudioPlayer.h"
@interface BufferChain : NSObject {
InputNode *inputNode;
ConverterNode *converterNode;
NSURL *streamURL;
id userInfo;

View File

@ -23,7 +23,6 @@
userInfo = nil;
inputNode = nil;
converterNode = nil;
}
return self;
@ -32,12 +31,10 @@
- (void)buildChain
{
[inputNode release];
[converterNode release];
inputNode = [[InputNode alloc] initWithController:self previous:nil];
converterNode = [[ConverterNode alloc] initWithController:self previous:inputNode];
finalNode = converterNode;
finalNode = inputNode;
}
- (BOOL)open:(NSURL *)url withOutputFormat:(AudioStreamBasicDescription)outputFormat
@ -55,13 +52,8 @@
}
if (![inputNode openURL:url withSource:source])
if (![inputNode openURL:url withSource:source outputFormat:outputFormat])
return NO;
AudioStreamBasicDescription inputFormat;
inputFormat = propertiesToASBD([inputNode properties]);
[converterNode setupWithInputFormat:inputFormat outputFormat:outputFormat ];
return YES;
}
@ -70,8 +62,6 @@
{
DBLog(@"LAUNCHING THREAD FOR INPUT");
[inputNode launchThread];
DBLog(@"LAUNCHING THREAD FOR CONVERTER");
[converterNode launchThread];
}
- (void)setUserInfo:(id)i
@ -92,8 +82,6 @@
[inputNode release];
[converterNode release];
[super dealloc];
}
@ -102,24 +90,16 @@
NSLog(@"SEEKING IN BUFFERCHIAN");
[inputNode seek:time];
[[converterNode readLock] lock];
[[converterNode writeLock] lock];
[[inputNode readLock] lock];
[[inputNode writeLock] lock];
//Signal so its waiting when we unlock
[[converterNode semaphore] signal];
[[inputNode semaphore] signal];
[converterNode resetBuffer];
[inputNode resetBuffer];
[[inputNode writeLock] unlock];
[[inputNode readLock] unlock];
[[converterNode writeLock] unlock];
[[converterNode readLock] unlock];
}
- (void)endOfInputReached
@ -149,7 +129,6 @@
- (void)setShouldContinue:(BOOL)s
{
[inputNode setShouldContinue:s];
[converterNode setShouldContinue:s];
}
@end

View File

@ -11,21 +11,23 @@
#import <CoreAudio/AudioHardware.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AudioUnit/AudioUnit.h>
#import "Node.h"
@interface ConverterNode : Node {
@interface Converter : NSObject
{
AudioConverterRef converter;
void *callbackBuffer;
void *buffer;
void *inputBuffer;
int inputBufferSize;
AudioStreamBasicDescription inputFormat;
AudioStreamBasicDescription outputFormat;
}
- (void *)buffer;
- (void)setupWithInputFormat:(AudioStreamBasicDescription)inputFormat outputFormat:(AudioStreamBasicDescription)outputFormat;
- (void)cleanUp;
- (void)process;
- (int)convert:(void *)dest amount:(int)amount;
@end

123
Audio/Chain/Converter.m Normal file
View File

@ -0,0 +1,123 @@
//
// ConverterNode.m
// Cog
//
// Created by Vincent Spader on 8/2/05.
// Copyright 2005 Vincent Spader. All rights reserved.
//
#import "Converter.h"
void PrintStreamDesc (AudioStreamBasicDescription *inDesc)
{
if (!inDesc) {
printf ("Can't print a NULL desc!\n");
return;
}
printf ("- - - - - - - - - - - - - - - - - - - -\n");
printf (" Sample Rate:%f\n", inDesc->mSampleRate);
printf (" Format ID:%s\n", (char*)&inDesc->mFormatID);
printf (" Format Flags:%lX\n", inDesc->mFormatFlags);
printf (" Bytes per Packet:%ld\n", inDesc->mBytesPerPacket);
printf (" Frames per Packet:%ld\n", inDesc->mFramesPerPacket);
printf (" Bytes per Frame:%ld\n", inDesc->mBytesPerFrame);
printf (" Channels per Frame:%ld\n", inDesc->mChannelsPerFrame);
printf (" Bits per Channel:%ld\n", inDesc->mBitsPerChannel);
printf ("- - - - - - - - - - - - - - - - - - - -\n");
}
@implementation Converter
//called from the complexfill when the audio is converted...good clean fun
static OSStatus ACInputProc(AudioConverterRef inAudioConverter, UInt32* ioNumberDataPackets, AudioBufferList* ioData, AudioStreamPacketDescription** outDataPacketDescription, void* inUserData)
{
Converter *converter = (Converter *)inUserData;
OSStatus err = noErr;
ioData->mBuffers[0].mData = converter->inputBuffer;
ioData->mBuffers[0].mDataByteSize = converter->inputBufferSize;
ioData->mBuffers[0].mNumberChannels = (converter->inputFormat.mChannelsPerFrame);
ioData->mNumberBuffers = 1;
return err;
}
- (int)convert:(void *)input amount:(int)inputSize
{
AudioBufferList ioData;
UInt32 ioNumberFrames;
int outputSize;
OSStatus err;
outputSize = inputSize;
UInt32 dataSize = sizeof(outputSize);
err = AudioConverterGetProperty(converter,
kAudioConverterPropertyCalculateOutputBufferSize,
&dataSize,
(void*)&outputSize);
if (buffer != NULL)
free(buffer);
buffer = malloc(outputSize);
ioNumberFrames = outputSize/outputFormat.mBytesPerFrame;
ioData.mBuffers[0].mData = buffer;
ioData.mBuffers[0].mDataByteSize = outputSize;
ioData.mBuffers[0].mNumberChannels = outputFormat.mChannelsPerFrame;
ioData.mNumberBuffers = 1;
inputBuffer = input;
inputBufferSize = inputSize;
err = AudioConverterFillComplexBuffer(converter, ACInputProc, self, &ioNumberFrames, &ioData, NULL);
if (err == kAudioConverterErr_InvalidInputSize) //It returns insz at EOS at times...so run it again to make sure all data is converted
{
return [self convert:input amount:inputSize];
}
return ioData.mBuffers[0].mDataByteSize;
}
- (void)setupWithInputFormat:(AudioStreamBasicDescription)inf outputFormat:(AudioStreamBasicDescription)outf
{
NSLog(@"CREATING THE CONVERTER");
//Make the converter
OSStatus stat = noErr;
inputFormat = inf;
outputFormat = outf;
stat = AudioConverterNew ( &inputFormat, &outputFormat, &converter);
if (stat != noErr)
{
NSLog(@"Error creating converter %i", stat);
}
if (inputFormat.mChannelsPerFrame == 1)
{
SInt32 channelMap[2] = { 0, 0 };
stat = AudioConverterSetProperty(converter,kAudioConverterChannelMap,sizeof(channelMap),channelMap);
if (stat != noErr)
{
NSLog(@"Error mapping channels %i", stat);
}
}
NSLog(@"Converter setup!");
PrintStreamDesc(&inf);
PrintStreamDesc(&outf);
}
- (void *)buffer
{
return buffer;
}
- (void)cleanUp
{
AudioConverterDispose(converter);
}
@end

View File

@ -1,216 +0,0 @@
//
// ConverterNode.m
// Cog
//
// Created by Vincent Spader on 8/2/05.
// Copyright 2005 Vincent Spader. All rights reserved.
//
#import "ConverterNode.h"
#define BUFFER_SIZE 512 * 1024
#define CHUNK_SIZE 16 * 1024
void PrintStreamDesc (AudioStreamBasicDescription *inDesc)
{
if (!inDesc) {
printf ("Can't print a NULL desc!\n");
return;
}
printf ("- - - - - - - - - - - - - - - - - - - -\n");
printf (" Sample Rate:%f\n", inDesc->mSampleRate);
printf (" Format ID:%s\n", (char*)&inDesc->mFormatID);
printf (" Format Flags:%lX\n", inDesc->mFormatFlags);
printf (" Bytes per Packet:%ld\n", inDesc->mBytesPerPacket);
printf (" Frames per Packet:%ld\n", inDesc->mFramesPerPacket);
printf (" Bytes per Frame:%ld\n", inDesc->mBytesPerFrame);
printf (" Channels per Frame:%ld\n", inDesc->mChannelsPerFrame);
printf (" Bits per Channel:%ld\n", inDesc->mBitsPerChannel);
printf ("- - - - - - - - - - - - - - - - - - - -\n");
}
@implementation ConverterNode
//called from the complexfill when the audio is converted...good clean fun
static OSStatus ACInputProc(AudioConverterRef inAudioConverter, UInt32* ioNumberDataPackets, AudioBufferList* ioData, AudioStreamPacketDescription** outDataPacketDescription, void* inUserData)
{
ConverterNode *converter = (ConverterNode *)inUserData;
OSStatus err = noErr;
int amountToWrite;
int amountRead;
if ([converter shouldContinue] == NO || [converter endOfStream] == YES)
{
// NSLog(@"END OF STREAM IN CONV");
ioData->mBuffers[0].mDataByteSize = 0;
*ioNumberDataPackets = 0;
return noErr;
}
amountToWrite = (*ioNumberDataPackets)*(converter->inputFormat.mBytesPerPacket);
if (converter->callbackBuffer != NULL)
free(converter->callbackBuffer);
converter->callbackBuffer = malloc(amountToWrite);
amountRead = [converter readData:converter->callbackBuffer amount:amountToWrite];
if (amountRead == 0)
{
ioData->mBuffers[0].mDataByteSize = 0;
*ioNumberDataPackets = 0;
return 100; //Keep asking for data
}
// NSLog(@"Amount read: %@ %i", converter, amountRead);
ioData->mBuffers[0].mData = converter->callbackBuffer;
ioData->mBuffers[0].mDataByteSize = amountRead;
ioData->mBuffers[0].mNumberChannels = (converter->inputFormat.mChannelsPerFrame);
ioData->mNumberBuffers = 1;
return err;
}
-(void)process
{
char writeBuf[CHUNK_SIZE];
int amountConverted;
while ([self shouldContinue] == YES) //Need to watch EOS somehow....
{
amountConverted = [self convert:writeBuf amount:CHUNK_SIZE];
// NSLog(@"Amount converted %@: %i %i", self, amountConverted, [self endOfStream]);
if (amountConverted == 0 && [self endOfStream] == YES)
{
// NSLog(@"END OF STREAM FOR ZINE DINNER!!!!");
return;
}
[self writeData:writeBuf amount:amountConverted];
}
/* void *writePtr;
int availOutput;
int amountConverted;
while ([self shouldContinue] == YES)
{
availOutput = [buffer lengthAvailableToWriteReturningPointer:&writePtr];
while (availOutput == 0)
{
[semaphore wait];
if (shouldContinue == NO)
{
return;
}
availOutput = [buffer lengthAvailableToWriteReturningPointer:&writePtr];
}
amountConverted = [self convert:writePtr amount:availOutput];
if (amountConverted > 0)
[buffer didWriteLength:amountConverted];
}
*/
}
- (int)convert:(void *)dest amount:(int)amount
{
AudioBufferList ioData;
UInt32 ioNumberFrames;
OSStatus err;
ioNumberFrames = amount/outputFormat.mBytesPerFrame;
ioData.mBuffers[0].mData = dest;
ioData.mBuffers[0].mDataByteSize = amount;
ioData.mBuffers[0].mNumberChannels = outputFormat.mChannelsPerFrame;
ioData.mNumberBuffers = 1;
err = AudioConverterFillComplexBuffer(converter, ACInputProc, self, &ioNumberFrames, &ioData, NULL);
if (err == kAudioConverterErr_InvalidInputSize) //It returns insz at EOS at times...so run it again to make sure all data is converted
{
return [self convert:dest amount:amount];
}
// if (err != noErr)
// NSLog(@"Converter error: %i", err);
return ioData.mBuffers[0].mDataByteSize;
/*
void *readPtr;
int availInput;
availInput = [[previousLink buffer] lengthAvailableToReadReturningPointer:&readPtr];
// NSLog(@"AMOUNT: %i %i", amount, availInput);
if (availInput == 0)
{
if ([previousLink endOfInput] == YES)
{
endOfInput = YES;
NSLog(@"EOI");
shouldContinue = NO;
return 0;
}
}
if (availInput < amount)
amount = availInput;
memcpy(dest, readPtr, amount);
if (amount > 0)
{
// NSLog(@"READ: %i", amount);
[[previousLink buffer] didReadLength:amount];
[[previousLink semaphore] signal];
}
return amount;
*/
}
- (void)setupWithInputFormat:(AudioStreamBasicDescription)inf outputFormat:(AudioStreamBasicDescription)outf
{
//Make the converter
OSStatus stat = noErr;
inputFormat = inf;
outputFormat = outf;
stat = AudioConverterNew ( &inputFormat, &outputFormat, &converter);
if (stat != noErr)
{
DBLog(@"Error creating converter %i", stat);
}
if (inputFormat.mChannelsPerFrame == 1)
{
SInt32 channelMap[2] = { 0, 0 };
stat = AudioConverterSetProperty(converter,kAudioConverterChannelMap,sizeof(channelMap),channelMap);
if (stat != noErr)
{
DBLog(@"Error mapping channels %i", stat);
}
}
// DBLog(@"Created converter");
PrintStreamDesc(&inf);
PrintStreamDesc(&outf);
}
- (void)cleanUp
{
AudioConverterDispose(converter);
}
@end

View File

@ -13,20 +13,25 @@
#import <AudioUnit/AudioUnit.h>
#import "AudioDecoder.h"
#import "Converter.h"
#import "Node.h"
#import "Plugin.h"
@interface InputNode : Node {
id<CogDecoder> decoder;
Converter *converter;
AudioStreamBasicDescription outputFormat;
BOOL shouldSeek;
double seekTime;
}
- (BOOL)openURL:(NSURL *)url withSource:(id<CogSource>)source;
- (BOOL)openURL:(NSURL *)url withSource:(id<CogSource>)source outputFormat:(AudioStreamBasicDescription)of;
- (void)process;
- (NSDictionary *) properties;
- (void)seek:(double)time;
- (void)registerObservers;
@end

View File

@ -9,15 +9,24 @@
#import "InputNode.h"
#import "BufferChain.h"
#import "Plugin.h"
#import "CoreAudioUtils.h"
@implementation InputNode
- (BOOL)openURL:(NSURL *)url withSource:(id<CogSource>)source
- (BOOL)openURL:(NSURL *)url withSource:(id<CogSource>)source outputFormat:(AudioStreamBasicDescription)of
{
outputFormat = of;
NSLog(@"Opening: %@", url);
decoder = [AudioDecoder audioDecoderForURL:url];
[decoder retain];
converter = [[Converter alloc] init];
if (converter == nil)
return NO;
[self registerObservers];
NSLog(@"Got decoder...%@", decoder);
if (decoder == nil)
return NO;
@ -27,17 +36,7 @@
NSLog(@"Couldn't open decoder...");
return NO;
}
/* while (decoder == nil)
{
NSURL *nextStream = [controller invalidDecoder];
if (nextStream == nil)
return NO;
decoder = [AudioDecoder audioDecoderForURL:nextStream];
[decoder open:nextStream];
}
*/
shouldContinue = YES;
shouldSeek = NO;
@ -45,11 +44,45 @@
return YES;
}
- (void)registerObservers
{
[decoder addObserver:self
forKeyPath:@"properties"
options:(NSKeyValueObservingOptionNew)
context:NULL];
NSLog(@"ADDED OBSERVER!!!");
[decoder addObserver:self
forKeyPath:@"metadata"
options:(NSKeyValueObservingOptionNew)
context:NULL];
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if ([keyPath isEqual:@"properties"]) {
NSLog(@"Properties changed!");
//Setup converter!
[converter cleanUp];
NSLog(@"CLEANED UP");
[converter setupWithInputFormat:propertiesToASBD([decoder properties]) outputFormat:outputFormat];
NSLog(@"CREATED CONVERTED");
//Inform something of properties change
}
else if ([keyPath isEqual:@"metadata"]) {
//Inform something of metadata change
}
}
- (void)process
{
const int chunk_size = CHUNK_SIZE;
char *buf;
int amountRead;
int amountRead, amountConverted;
NSLog(@"Playing file: %i", self);
buf = malloc(chunk_size);
@ -63,19 +96,23 @@
shouldSeek = NO;
}
amountRead = [decoder fillBuffer:buf ofSize: chunk_size];
if (amountRead <= 0)
amountRead = [decoder fillBuffer:buf ofSize:chunk_size];
amountConverted = [converter convert:buf amount:amountRead]; //Convert fills in converter buffer, til the next call
if (amountConverted <= 0)
{
endOfStream = YES;
DBLog(@"END OF INPUT WAS REACHED");
[controller endOfInputReached];
break; //eof
}
[self writeData:buf amount:amountRead];
[self writeData:[converter buffer] amount:amountConverted];
}
free(buf);
[decoder close];
[converter cleanUp];
NSLog(@"CLOSED: %i", self);
}
@ -89,6 +126,9 @@
- (void)dealloc
{
[decoder removeObserver:self forKeyPath:@"properties"];
[decoder removeObserver:self forKeyPath:@"metadata"];
[decoder release];
[super dealloc];

View File

@ -17,8 +17,6 @@
17C940240B900909008627D6 /* AudioMetadataReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 17C940220B900909008627D6 /* AudioMetadataReader.m */; };
17D21CA10B8BE4BA00D1EBDE /* BufferChain.h in Headers */ = {isa = PBXBuildFile; fileRef = 17D21C760B8BE4BA00D1EBDE /* BufferChain.h */; settings = {ATTRIBUTES = (Public, ); }; };
17D21CA20B8BE4BA00D1EBDE /* BufferChain.m in Sources */ = {isa = PBXBuildFile; fileRef = 17D21C770B8BE4BA00D1EBDE /* BufferChain.m */; };
17D21CA30B8BE4BA00D1EBDE /* ConverterNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 17D21C780B8BE4BA00D1EBDE /* ConverterNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
17D21CA40B8BE4BA00D1EBDE /* ConverterNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 17D21C790B8BE4BA00D1EBDE /* ConverterNode.m */; };
17D21CA50B8BE4BA00D1EBDE /* InputNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 17D21C7A0B8BE4BA00D1EBDE /* InputNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
17D21CA60B8BE4BA00D1EBDE /* InputNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 17D21C7B0B8BE4BA00D1EBDE /* InputNode.m */; };
17D21CA70B8BE4BA00D1EBDE /* Node.h in Headers */ = {isa = PBXBuildFile; fileRef = 17D21C7C0B8BE4BA00D1EBDE /* Node.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -46,6 +44,8 @@
17F94DD60B8D0F7000A34E87 /* PluginController.m in Sources */ = {isa = PBXBuildFile; fileRef = 17F94DD40B8D0F7000A34E87 /* PluginController.m */; };
17F94DDD0B8D101100A34E87 /* Plugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F94DDC0B8D101100A34E87 /* Plugin.h */; settings = {ATTRIBUTES = (Public, ); }; };
8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
8EC1225F0B993BD500C5B3AD /* Converter.h in Headers */ = {isa = PBXBuildFile; fileRef = 8EC1225D0B993BD500C5B3AD /* Converter.h */; };
8EC122600B993BD500C5B3AD /* Converter.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EC1225E0B993BD500C5B3AD /* Converter.m */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@ -74,8 +74,6 @@
17C940220B900909008627D6 /* AudioMetadataReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AudioMetadataReader.m; sourceTree = "<group>"; };
17D21C760B8BE4BA00D1EBDE /* BufferChain.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = BufferChain.h; sourceTree = "<group>"; };
17D21C770B8BE4BA00D1EBDE /* BufferChain.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = BufferChain.m; sourceTree = "<group>"; };
17D21C780B8BE4BA00D1EBDE /* ConverterNode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ConverterNode.h; sourceTree = "<group>"; };
17D21C790B8BE4BA00D1EBDE /* ConverterNode.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = ConverterNode.m; sourceTree = "<group>"; };
17D21C7A0B8BE4BA00D1EBDE /* InputNode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = InputNode.h; sourceTree = "<group>"; };
17D21C7B0B8BE4BA00D1EBDE /* InputNode.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = InputNode.m; sourceTree = "<group>"; };
17D21C7C0B8BE4BA00D1EBDE /* Node.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Node.h; sourceTree = "<group>"; };
@ -105,6 +103,8 @@
32DBCF5E0370ADEE00C91783 /* CogAudio_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CogAudio_Prefix.pch; sourceTree = "<group>"; };
8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
8DC2EF5B0486A6940098B216 /* CogAudio.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CogAudio.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8EC1225D0B993BD500C5B3AD /* Converter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Converter.h; sourceTree = "<group>"; };
8EC1225E0B993BD500C5B3AD /* Converter.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = Converter.m; sourceTree = "<group>"; };
D2F7E79907B2D74100F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
/* End PBXFileReference section */
@ -213,8 +213,8 @@
children = (
17D21C760B8BE4BA00D1EBDE /* BufferChain.h */,
17D21C770B8BE4BA00D1EBDE /* BufferChain.m */,
17D21C780B8BE4BA00D1EBDE /* ConverterNode.h */,
17D21C790B8BE4BA00D1EBDE /* ConverterNode.m */,
8EC1225D0B993BD500C5B3AD /* Converter.h */,
8EC1225E0B993BD500C5B3AD /* Converter.m */,
17D21C7A0B8BE4BA00D1EBDE /* InputNode.h */,
17D21C7B0B8BE4BA00D1EBDE /* InputNode.m */,
17D21C7C0B8BE4BA00D1EBDE /* Node.h */,
@ -288,7 +288,6 @@
buildActionMask = 2147483647;
files = (
17D21CA10B8BE4BA00D1EBDE /* BufferChain.h in Headers */,
17D21CA30B8BE4BA00D1EBDE /* ConverterNode.h in Headers */,
17D21CA50B8BE4BA00D1EBDE /* InputNode.h in Headers */,
17D21CA70B8BE4BA00D1EBDE /* Node.h in Headers */,
17D21CA90B8BE4BA00D1EBDE /* OutputNode.h in Headers */,
@ -305,6 +304,7 @@
17C940230B900909008627D6 /* AudioMetadataReader.h in Headers */,
17B619300B909BC300BC003F /* AudioPropertiesReader.h in Headers */,
17ADB13C0B97926D00257CA2 /* AudioSource.h in Headers */,
8EC1225F0B993BD500C5B3AD /* Converter.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -363,7 +363,6 @@
buildActionMask = 2147483647;
files = (
17D21CA20B8BE4BA00D1EBDE /* BufferChain.m in Sources */,
17D21CA40B8BE4BA00D1EBDE /* ConverterNode.m in Sources */,
17D21CA60B8BE4BA00D1EBDE /* InputNode.m in Sources */,
17D21CA80B8BE4BA00D1EBDE /* Node.m in Sources */,
17D21CAA0B8BE4BA00D1EBDE /* OutputNode.m in Sources */,
@ -378,6 +377,7 @@
17C940240B900909008627D6 /* AudioMetadataReader.m in Sources */,
17B619310B909BC300BC003F /* AudioPropertiesReader.m in Sources */,
17ADB13D0B97926D00257CA2 /* AudioSource.m in Sources */,
8EC122600B993BD500C5B3AD /* Converter.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -28,11 +28,14 @@
- (void)close;
@end
@protocol CogDecoder <NSObject>
@protocol CogDecoder <NSObject>
+ (NSArray *)fileTypes; //mp3, ogg, etc
- (BOOL)open:(id<CogSource>)source;
//For KVO
//- (void)setProperties:(NSDictionary *)p;
- (NSDictionary *)properties;
- (BOOL)open:(id<CogSource>)source;
- (BOOL)seekable;
- (double)seekToTime:(double)time; //time is in milleseconds, should return the time actually seeked to.
- (int)fillBuffer:(void *)buf ofSize:(UInt32)size;

View File

@ -21,10 +21,5 @@
#import <Cocoa/Cocoa.h>
#import <AudioToolbox/AudioToolbox.h>
// Return an array of valid audio file extensions recognized by Core Audio
NSArray * getCoreAudioExtensions();
AudioStreamBasicDescription propertiesToASBD(NSDictionary *properties);
NSDictionary *ASBDToProperties(AudioStreamBasicDescription asbd);
BOOL hostIsBigEndian();
//NSDictionary *ASBDToProperties(AudioStreamBasicDescription asbd);

View File

@ -22,32 +22,6 @@
#include <AudioToolbox/AudioFile.h>
// CoreAudio utility function
static NSArray *sAudioExtensions = nil;
// Return an array of valid audio file extensions recognized by Core Audio
NSArray *
getCoreAudioExtensions()
{
OSStatus err;
UInt32 size;
@synchronized(sAudioExtensions) {
if(nil == sAudioExtensions) {
size = sizeof(sAudioExtensions);
err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_AllExtensions, 0, NULL, &size, &sAudioExtensions);
if(noErr != err) {
return nil;
}
[sAudioExtensions retain];
}
}
return sAudioExtensions;
}
BOOL hostIsBigEndian()
{
#ifdef __BIG_ENDIAN__

View File

@ -272,7 +272,10 @@ int parse_headers(struct xing *xing, struct lame *lame, struct mad_bitptr ptr, u
bitrate /= 1000;
[_source seek:0 whence:SEEK_SET];
[self willChangeValueForKey:@"properties"];
[self didChangeValueForKey:@"properties"];
return frames != 0;
}

View File

@ -22,7 +22,7 @@
@interface VorbisDecoder : NSObject <CogDecoder>
{
id<CogSource> source;
OggVorbis_File vorbisRef;
int currentSection;
int lastSection;

View File

@ -71,7 +71,9 @@ long sourceTell(void *datasource)
length = 0.0;//((double)ov_pcm_total(&vorbisRef, -1) * 1000.0)/frequency;
NSLog(@"Ok to go WITH OGG. %i", seekable);
[self willChangeValueForKey:@"properties"];
[self didChangeValueForKey:@"properties"];
return YES;
}