[Input API] Change input readAudio method
readAudio now returns an AudioChunk object directly, and all inputs have been changed to accomodate this. Also, input and converter processing have been altered to better work with this. Signed-off-by: Christopher Snowhill <kode54@gmail.com>xcode15
parent
c43ebba424
commit
8d851e5bda
|
@ -80,6 +80,7 @@ enum {
|
|||
+ (uint32_t)findChannelIndex:(uint32_t)flag;
|
||||
|
||||
- (id)init;
|
||||
- (id)initWithProperties:(NSDictionary *)properties;
|
||||
|
||||
- (void)assignSamples:(const void *)data frameCount:(size_t)count;
|
||||
|
||||
|
@ -88,6 +89,7 @@ enum {
|
|||
- (BOOL)isEmpty;
|
||||
|
||||
- (size_t)frameCount;
|
||||
- (void)setFrameCount:(size_t)count; // For truncation only
|
||||
|
||||
- (double)duration;
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#import "AudioChunk.h"
|
||||
|
||||
#import "CoreAudioUtils.h"
|
||||
|
||||
@implementation AudioChunk
|
||||
|
||||
- (id)init {
|
||||
|
@ -21,6 +23,18 @@
|
|||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithProperties:(NSDictionary *)properties {
|
||||
self = [super init];
|
||||
|
||||
if(self) {
|
||||
chunkData = [[NSMutableData alloc] init];
|
||||
[self setFormat:propertiesToASBD(properties)];
|
||||
lossless = [[properties objectForKey:@"encoding"] isEqualToString:@"lossless"];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static const uint32_t AudioChannelConfigTable[] = {
|
||||
0,
|
||||
AudioConfigMono,
|
||||
|
@ -156,6 +170,16 @@ static const uint32_t AudioChannelConfigTable[] = {
|
|||
return 0;
|
||||
}
|
||||
|
||||
- (void)setFrameCount:(size_t)count {
|
||||
if(formatAssigned) {
|
||||
count *= format.mBytesPerPacket;
|
||||
size_t currentLength = [chunkData length];
|
||||
if(count < currentLength) {
|
||||
[chunkData replaceBytesInRange:NSMakeRange(count, currentLength - count) withBytes:NULL length:0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (double)duration {
|
||||
if(formatAssigned) {
|
||||
const size_t bytesPerPacket = format.mBytesPerPacket;
|
||||
|
|
|
@ -432,34 +432,32 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
|
|||
}
|
||||
|
||||
- (void)process {
|
||||
char writeBuf[CHUNK_SIZE];
|
||||
|
||||
// Removed endOfStream check from here, since we want to be able to flush the converter
|
||||
// when the end of stream is reached. Convert function instead processes what it can,
|
||||
// and returns 0 samples when it has nothing more to process at the end of stream.
|
||||
while([self shouldContinue] == YES) {
|
||||
int amountConverted;
|
||||
AudioChunk *chunk = nil;
|
||||
while(paused) {
|
||||
usleep(500);
|
||||
}
|
||||
@autoreleasepool {
|
||||
amountConverted = [self convert:writeBuf amount:CHUNK_SIZE];
|
||||
chunk = [self convert];
|
||||
}
|
||||
if(!amountConverted) {
|
||||
if(paused) {
|
||||
continue;
|
||||
} else if(streamFormatChanged) {
|
||||
[self cleanUp];
|
||||
[self setupWithInputFormat:newInputFormat withInputConfig:newInputChannelConfig isLossless:rememberedLossless];
|
||||
continue;
|
||||
} else
|
||||
break;
|
||||
if(!chunk) {
|
||||
continue;
|
||||
}
|
||||
@autoreleasepool {
|
||||
[self writeChunk:chunk];
|
||||
chunk = nil;
|
||||
}
|
||||
if(streamFormatChanged) {
|
||||
[self cleanUp];
|
||||
[self setupWithInputFormat:newInputFormat withInputConfig:newInputChannelConfig isLossless:rememberedLossless];
|
||||
}
|
||||
[self writeData:writeBuf amount:amountConverted];
|
||||
}
|
||||
}
|
||||
|
||||
- (int)convert:(void *)dest amount:(int)amount {
|
||||
- (AudioChunk *)convert {
|
||||
UInt32 ioNumberPackets;
|
||||
int amountReadFromFC;
|
||||
int amountRead = 0;
|
||||
|
@ -472,7 +470,7 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
|
|||
tryagain:
|
||||
if(stopping || [self shouldContinue] == NO) {
|
||||
convertEntered = NO;
|
||||
return amountRead;
|
||||
return nil;
|
||||
}
|
||||
|
||||
amountReadFromFC = 0;
|
||||
|
@ -543,7 +541,7 @@ tryagain:
|
|||
|
||||
if(!bytesReadFromInput) {
|
||||
convertEntered = NO;
|
||||
return amountRead;
|
||||
return nil;
|
||||
}
|
||||
|
||||
if(bytesReadFromInput && isBigEndian) {
|
||||
|
@ -703,19 +701,22 @@ tryagain:
|
|||
if(floatOffset == floatSize)
|
||||
goto tryagain;
|
||||
|
||||
ioNumberPackets = (amount - amountRead);
|
||||
if(ioNumberPackets > (floatSize - floatOffset))
|
||||
ioNumberPackets = (UInt32)(floatSize - floatOffset);
|
||||
ioNumberPackets = (UInt32)(floatSize - floatOffset);
|
||||
|
||||
ioNumberPackets -= ioNumberPackets % dmFloatFormat.mBytesPerPacket;
|
||||
|
||||
memcpy(((uint8_t *)dest) + amountRead, ((uint8_t *)floatBuffer) + floatOffset, ioNumberPackets);
|
||||
AudioChunk *chunk = [[AudioChunk alloc] init];
|
||||
[chunk setFormat:nodeFormat];
|
||||
if(nodeChannelConfig) {
|
||||
[chunk setChannelConfig:nodeChannelConfig];
|
||||
}
|
||||
[chunk assignSamples:floatBuffer frameCount:ioNumberPackets / dmFloatFormat.mBytesPerPacket];
|
||||
|
||||
floatOffset += ioNumberPackets;
|
||||
amountRead += ioNumberPackets;
|
||||
|
||||
convertEntered = NO;
|
||||
return amountRead;
|
||||
return chunk;
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath
|
||||
|
|
|
@ -142,10 +142,6 @@ static void *kInputNodeContext = &kInputNodeContext;
|
|||
}
|
||||
|
||||
- (void)process {
|
||||
int amountInBuffer = 0;
|
||||
int bytesInBuffer = 0;
|
||||
void *inputBuffer = malloc(CHUNK_SIZE * 8 * 18); // Maximum 18 channels, dunno what we'll receive
|
||||
|
||||
BOOL shouldClose = YES;
|
||||
BOOL seekError = NO;
|
||||
|
||||
|
@ -165,7 +161,6 @@ static void *kInputNodeContext = &kInputNodeContext;
|
|||
ConverterNode *converter = [bufferChain converter];
|
||||
DLog(@"SEEKING! Resetting Buffer");
|
||||
|
||||
amountInBuffer = 0;
|
||||
// This resets the converter's buffer
|
||||
[self resetBuffer];
|
||||
[converter resetBuffer];
|
||||
|
@ -174,7 +169,9 @@ static void *kInputNodeContext = &kInputNodeContext;
|
|||
DLog(@"Reset buffer!");
|
||||
|
||||
DLog(@"SEEKING!");
|
||||
seekError = [decoder seek:seekFrame] < 0;
|
||||
@autoreleasepool {
|
||||
seekError = [decoder seek:seekFrame] < 0;
|
||||
}
|
||||
|
||||
shouldSeek = NO;
|
||||
DLog(@"Seeked! Resetting Buffer");
|
||||
|
@ -185,44 +182,39 @@ static void *kInputNodeContext = &kInputNodeContext;
|
|||
}
|
||||
}
|
||||
|
||||
if(amountInBuffer < CHUNK_SIZE) {
|
||||
int framesToRead = CHUNK_SIZE - amountInBuffer;
|
||||
int framesRead;
|
||||
AudioChunk *chunk;
|
||||
@autoreleasepool {
|
||||
chunk = [decoder readAudio];
|
||||
}
|
||||
|
||||
if(chunk) {
|
||||
@autoreleasepool {
|
||||
framesRead = [decoder readAudio:((char *)inputBuffer) + bytesInBuffer frames:framesToRead];
|
||||
[self writeChunk:chunk];
|
||||
chunk = nil;
|
||||
}
|
||||
} else {
|
||||
DLog(@"End of stream? %@", [self properties]);
|
||||
|
||||
endOfStream = YES;
|
||||
shouldClose = [controller endOfInputReached]; // Lets us know if we should keep going or not (occassionally, for track changes within a file)
|
||||
DLog(@"closing? is %i", shouldClose);
|
||||
|
||||
// Move this here, so that the above endOfInputReached has a chance to queue another track before starting output
|
||||
// Technically, the output should still play out its buffer first before checking if it should stop
|
||||
if(initialBufferFilled == NO) {
|
||||
[controller initialBufferFilled:self];
|
||||
}
|
||||
|
||||
if(framesRead > 0 && !seekError) {
|
||||
amountInBuffer += framesRead;
|
||||
bytesInBuffer += framesRead * bytesPerFrame;
|
||||
[self writeData:inputBuffer amount:bytesInBuffer];
|
||||
amountInBuffer = 0;
|
||||
bytesInBuffer = 0;
|
||||
// wait before exiting, as we might still get seeking request
|
||||
DLog("InputNode: Before wait")
|
||||
[exitAtTheEndOfTheStream waitIndefinitely];
|
||||
DLog("InputNode: After wait, should seek = %d", shouldSeek);
|
||||
if(shouldSeek) {
|
||||
endOfStream = NO;
|
||||
shouldClose = NO;
|
||||
continue;
|
||||
} else {
|
||||
DLog(@"End of stream? %@", [self properties]);
|
||||
|
||||
endOfStream = YES;
|
||||
shouldClose = [controller endOfInputReached]; // Lets us know if we should keep going or not (occassionally, for track changes within a file)
|
||||
DLog(@"closing? is %i", shouldClose);
|
||||
|
||||
// Move this here, so that the above endOfInputReached has a chance to queue another track before starting output
|
||||
// Technically, the output should still play out its buffer first before checking if it should stop
|
||||
if(initialBufferFilled == NO) {
|
||||
[controller initialBufferFilled:self];
|
||||
}
|
||||
|
||||
// wait before exiting, as we might still get seeking request
|
||||
DLog("InputNode: Before wait")
|
||||
[exitAtTheEndOfTheStream waitIndefinitely];
|
||||
DLog("InputNode: After wait, should seek = %d", shouldSeek);
|
||||
if(shouldSeek) {
|
||||
endOfStream = NO;
|
||||
shouldClose = NO;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -230,8 +222,6 @@ static void *kInputNodeContext = &kInputNodeContext;
|
|||
if(shouldClose)
|
||||
[decoder close];
|
||||
|
||||
free(inputBuffer);
|
||||
|
||||
[exitAtTheEndOfTheStream signal];
|
||||
|
||||
DLog("Input node thread stopping");
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
ChunkList *buffer;
|
||||
Semaphore *semaphore;
|
||||
|
||||
NSRecursiveLock *accessLock;
|
||||
NSLock *accessLock;
|
||||
|
||||
id __weak previousNode;
|
||||
id __weak controller;
|
||||
|
@ -37,6 +37,7 @@
|
|||
- (id _Nullable)initWithController:(id _Nonnull)c previous:(id _Nullable)p;
|
||||
|
||||
- (void)writeData:(const void *_Nonnull)ptr amount:(size_t)a;
|
||||
- (void)writeChunk:(AudioChunk *_Nonnull)chunk;
|
||||
- (AudioChunk *_Nonnull)readChunk:(size_t)maxFrames;
|
||||
|
||||
- (BOOL)peekFormat:(AudioStreamBasicDescription *_Nonnull)format channelConfig:(uint32_t *_Nonnull)config;
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
buffer = [[ChunkList alloc] initWithMaximumDuration:3.0];
|
||||
semaphore = [[Semaphore alloc] init];
|
||||
|
||||
accessLock = [[NSRecursiveLock alloc] init];
|
||||
accessLock = [[NSLock alloc] init];
|
||||
|
||||
initialBufferFilled = NO;
|
||||
|
||||
|
@ -91,6 +91,35 @@
|
|||
[accessLock unlock];
|
||||
}
|
||||
|
||||
- (void)writeChunk:(AudioChunk *)chunk {
|
||||
[accessLock lock];
|
||||
|
||||
const double chunkDuration = [chunk duration];
|
||||
double durationLeft = [buffer maxDuration] - [buffer listDuration];
|
||||
|
||||
while(shouldContinue == YES && chunkDuration > durationLeft) {
|
||||
if(durationLeft < chunkDuration) {
|
||||
if(initialBufferFilled == NO) {
|
||||
initialBufferFilled = YES;
|
||||
if([controller respondsToSelector:@selector(initialBufferFilled:)])
|
||||
[controller performSelector:@selector(initialBufferFilled:) withObject:self];
|
||||
}
|
||||
}
|
||||
|
||||
if(durationLeft < chunkDuration || shouldReset) {
|
||||
[accessLock unlock];
|
||||
[semaphore wait];
|
||||
[accessLock lock];
|
||||
}
|
||||
|
||||
durationLeft = [buffer maxDuration] - [buffer listDuration];
|
||||
}
|
||||
|
||||
[buffer addChunk:chunk];
|
||||
|
||||
[accessLock unlock];
|
||||
}
|
||||
|
||||
// Should be overwriten by subclass.
|
||||
- (void)process {
|
||||
}
|
||||
|
|
|
@ -79,9 +79,9 @@ static void *kCogDecoderMultiContext = &kCogDecoderMultiContext;
|
|||
return @{};
|
||||
}
|
||||
|
||||
- (int)readAudio:(void *)buffer frames:(UInt32)frames {
|
||||
if(theDecoder != nil) return [theDecoder readAudio:buffer frames:frames];
|
||||
return 0;
|
||||
- (AudioChunk *)readAudio {
|
||||
if(theDecoder != nil) return [theDecoder readAudio];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL)open:(id<CogSource>)source {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// Plugins! HOORAY!
|
||||
|
||||
#import "AudioChunk.h"
|
||||
|
||||
@protocol CogSource <NSObject>
|
||||
+ (NSArray *)schemes; // http, file, etc
|
||||
|
||||
|
@ -42,7 +44,7 @@
|
|||
- (NSDictionary *)properties;
|
||||
- (NSDictionary *)metadata; // Only to be implemented for dynamic metadata, send events on change
|
||||
|
||||
- (int)readAudio:(void *)buffer frames:(UInt32)frames;
|
||||
- (AudioChunk *)readAudio;
|
||||
|
||||
- (BOOL)open:(id<CogSource>)source;
|
||||
- (long)seek:(long)frame;
|
||||
|
|
|
@ -930,6 +930,7 @@
|
|||
83489C4E2782F2DF00BDCEA2 /* libvgmPlayer.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libvgmPlayer.xcodeproj; path = Plugins/libvgmPlayer/libvgmPlayer.xcodeproj; sourceTree = "<group>"; };
|
||||
8349270127B4EFFC0009AB2B /* duplicateItemsTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = duplicateItemsTemplate.pdf; path = Images/duplicateItemsTemplate.pdf; sourceTree = "<group>"; };
|
||||
8349270B27B4EFFC0009AB2B /* deadItemsTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = deadItemsTemplate.pdf; path = Images/deadItemsTemplate.pdf; sourceTree = "<group>"; };
|
||||
834A42C4287B01B600EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = Audio/Chain/AudioChunk.h; sourceTree = SOURCE_ROOT; };
|
||||
834B05E82859C006000B7DC0 /* TotalTimeTransformer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TotalTimeTransformer.h; path = Transformers/TotalTimeTransformer.h; sourceTree = "<group>"; };
|
||||
834B05E92859C006000B7DC0 /* TotalTimeTransformer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = TotalTimeTransformer.m; path = Transformers/TotalTimeTransformer.m; sourceTree = "<group>"; };
|
||||
8355D6B4180612F300D05687 /* NSData+MD5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+MD5.h"; sourceTree = "<group>"; };
|
||||
|
@ -1233,6 +1234,7 @@
|
|||
177EC0110B8BC2CF0000BC8C /* Utils */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42C4287B01B600EB9D9B /* AudioChunk.h */,
|
||||
8384912518080F2D00E7332D /* Logging.h */,
|
||||
07E18DF10D62B38400BB0E11 /* NSArray+ShuffleUtils.h */,
|
||||
07E18DF20D62B38400BB0E11 /* NSArray+ShuffleUtils.m */,
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
089C167FFE841241C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
|
||||
1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
|
||||
32DBCF630370AF2F00C91783 /* APL_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APL_Prefix.pch; sourceTree = "<group>"; };
|
||||
834A42AF287AF34300EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
83747FE32862E8B60021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
|
||||
838491281808135500E7332D /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logging.h; path = ../../Utils/Logging.h; sourceTree = "<group>"; };
|
||||
8D5B49B7048680CD000E48DA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
|
@ -74,6 +75,7 @@
|
|||
08FB77AFFE84173DC02AAC07 /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42AF287AF34300EB9D9B /* AudioChunk.h */,
|
||||
838491281808135500E7332D /* Logging.h */,
|
||||
8E8D423C0CBB0FF600135C1B /* Plugin.h */,
|
||||
8E8D42350CBB0F9800135C1B /* APLDecoder.h */,
|
||||
|
|
|
@ -108,18 +108,24 @@
|
|||
return framePosition;
|
||||
}
|
||||
|
||||
- (int)readAudio:(void *)buf frames:(UInt32)frames {
|
||||
if(framePosition + frames > trackEnd)
|
||||
frames = (UInt32)(trackEnd - framePosition);
|
||||
- (AudioChunk *)readAudio {
|
||||
int maxFrames = INT_MAX;
|
||||
|
||||
if(!frames) {
|
||||
if(framePosition + maxFrames > trackEnd)
|
||||
maxFrames = (int)(trackEnd - framePosition);
|
||||
|
||||
if(!maxFrames) {
|
||||
DLog(@"APL readAudio Returning 0");
|
||||
return 0;
|
||||
return nil;
|
||||
}
|
||||
|
||||
int n = [decoder readAudio:buf frames:frames];
|
||||
framePosition += n;
|
||||
return n;
|
||||
AudioChunk *chunk = [decoder readAudio];
|
||||
if(chunk.frameCount > maxFrames) {
|
||||
[chunk setFrameCount:maxFrames];
|
||||
}
|
||||
|
||||
framePosition += chunk.frameCount;
|
||||
return chunk;
|
||||
}
|
||||
|
||||
- (BOOL)isSilence {
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
|
||||
/* Begin PBXFileReference section */
|
||||
833A8999286FF2FD0022E036 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
|
||||
834A42AE287AF27A00EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
83747C6D2862DDDB0021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
|
||||
83D3C5F3201C674D005564CB /* AdPlug.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AdPlug.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
83D3C5F6201C674D005564CB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
|
@ -123,6 +124,7 @@
|
|||
83D3C5F5201C674D005564CB /* AdPlug */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42AE287AF27A00EB9D9B /* AudioChunk.h */,
|
||||
83D3C667201C7020005564CB /* adplug.db */,
|
||||
83D3C657201C6E24005564CB /* AdPlugContainer.h */,
|
||||
83D3C654201C6E24005564CB /* AdPlugContainer.mm */,
|
||||
|
|
|
@ -103,7 +103,14 @@ static CAdPlugDatabase *g_database = NULL;
|
|||
return @{};
|
||||
}
|
||||
|
||||
- (int)readAudio:(void *)buf frames:(UInt32)frames {
|
||||
- (AudioChunk *)readAudio {
|
||||
int frames = 1024;
|
||||
int16_t buffer[1024 * 2];
|
||||
|
||||
id audioChunkClass = NSClassFromString(@"AudioChunk");
|
||||
AudioChunk *chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
|
||||
void *buf = (void *)buffer;
|
||||
|
||||
int total = 0;
|
||||
bool dont_loop = !IsRepeatOneSet();
|
||||
if(dont_loop && current_pos + frames > length)
|
||||
|
@ -128,7 +135,9 @@ static CAdPlugDatabase *g_database = NULL;
|
|||
total += samples_now;
|
||||
}
|
||||
|
||||
return total;
|
||||
[chunk assignSamples:buffer frameCount:total];
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
- (long)seek:(long)frame {
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
/* Begin PBXFileReference section */
|
||||
8307D31A286070EA000FF8EB /* SandboxBroker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SandboxBroker.h; path = ../../../Utils/SandboxBroker.h; sourceTree = "<group>"; };
|
||||
834A42B0287AF4BF00EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
8359009717FEF6490060F3ED /* ArchiveSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArchiveSource.h; sourceTree = "<group>"; };
|
||||
8359009817FEF6490060F3ED /* ArchiveSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ArchiveSource.m; sourceTree = "<group>"; };
|
||||
8359009A17FEFDA80060F3ED /* ArchiveContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArchiveContainer.h; sourceTree = "<group>"; };
|
||||
|
@ -105,6 +106,7 @@
|
|||
8359FF2017FEF35C0060F3ED /* ArchiveSource */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42B0287AF4BF00EB9D9B /* AudioChunk.h */,
|
||||
8307D31A286070EA000FF8EB /* SandboxBroker.h */,
|
||||
8384913518081BA000E7332D /* Logging.h */,
|
||||
835900A017FF079C0060F3ED /* Plugin.h */,
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
17C93EAB0B8FF3CE008627D6 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = /System/Library/Frameworks/CoreAudio.framework; sourceTree = "<absolute>"; };
|
||||
17C93EB20B8FF3E1008627D6 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = /System/Library/Frameworks/AudioToolbox.framework; sourceTree = "<absolute>"; };
|
||||
32DBCF630370AF2F00C91783 /* CoreAudio_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CoreAudio_Prefix.pch; sourceTree = "<group>"; };
|
||||
834A42B1287AF4D900EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
83747C5E2862DD880021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
|
||||
83849129180813E800E7332D /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logging.h; path = ../../Utils/Logging.h; sourceTree = "<group>"; };
|
||||
8D5B49B6048680CD000E48DA /* CoreAudio.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CoreAudio.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
|
@ -77,6 +78,7 @@
|
|||
08FB77AFFE84173DC02AAC07 /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42B1287AF4D900EB9D9B /* AudioChunk.h */,
|
||||
83849129180813E800E7332D /* Logging.h */,
|
||||
177FCFCA0B90C9A10011C3B5 /* Plugin.h */,
|
||||
17C93E720B8FF192008627D6 /* CoreAudioDecoder.h */,
|
||||
|
|
|
@ -306,25 +306,33 @@ static SInt64 getSizeProc(void *clientData) {
|
|||
return YES;
|
||||
}
|
||||
|
||||
- (int)readAudio:(void *)buf frames:(UInt32)frames {
|
||||
- (AudioChunk *)readAudio {
|
||||
OSStatus err;
|
||||
AudioBufferList bufferList;
|
||||
UInt32 frameCount;
|
||||
|
||||
int frames = 1024;
|
||||
size_t bytesPerFrame = channels * (bitsPerSample / 8);
|
||||
uint8_t buffer[frames * bytesPerFrame];
|
||||
|
||||
// Set up the AudioBufferList
|
||||
bufferList.mNumberBuffers = 1;
|
||||
bufferList.mBuffers[0].mNumberChannels = channels;
|
||||
bufferList.mBuffers[0].mData = buf;
|
||||
bufferList.mBuffers[0].mData = buffer;
|
||||
bufferList.mBuffers[0].mDataByteSize = frames * channels * (bitsPerSample / 8);
|
||||
|
||||
// Read a chunk of PCM input (converted from whatever format)
|
||||
frameCount = frames;
|
||||
err = ExtAudioFileRead(_in, &frameCount, &bufferList);
|
||||
if(err != noErr) {
|
||||
return 0;
|
||||
return nil;
|
||||
}
|
||||
|
||||
return frameCount;
|
||||
id audioChunkClass = NSClassFromString(@"AudioChunk");
|
||||
AudioChunk *chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
|
||||
[chunk assignSamples:buffer frameCount:frameCount];
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
- (long)seek:(long)frame {
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
17DA346D0CC04FCD0003F6B2 /* CueSheetMetadataReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CueSheetMetadataReader.m; sourceTree = "<group>"; };
|
||||
32DBCF630370AF2F00C91783 /* CueSheet_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CueSheet_Prefix.pch; sourceTree = "<group>"; };
|
||||
833F68371CDBCAB200AFB9F0 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
834A42B2287AF59900EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
835C888E22CC1883001B4B3F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
83747C592862DD660021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
|
||||
8384912A180814D900E7332D /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logging.h; path = ../../Utils/Logging.h; sourceTree = "<group>"; };
|
||||
|
@ -89,6 +90,7 @@
|
|||
08FB77AFFE84173DC02AAC07 /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42B2287AF59900EB9D9B /* AudioChunk.h */,
|
||||
839DA7D3274A2FD4001B18E5 /* NSDictionary+Merge.h */,
|
||||
839DA7D0274A2EA9001B18E5 /* AudioMetadataReader.h */,
|
||||
8384912A180814D900E7332D /* Logging.h */,
|
||||
|
|
|
@ -309,25 +309,32 @@ static void *kCueSheetDecoderContext = &kCueSheetDecoderContext;
|
|||
return framePosition - trackStart;
|
||||
}
|
||||
|
||||
- (int)readAudio:(void *)buf frames:(UInt32)frames {
|
||||
- (AudioChunk *)readAudio {
|
||||
if(!seekedToStart) {
|
||||
[self seek:0];
|
||||
}
|
||||
|
||||
int frames = INT_MAX;
|
||||
|
||||
if(!noFragment && framePosition + frames > trackEnd) {
|
||||
frames = (UInt32)(trackEnd - framePosition);
|
||||
}
|
||||
|
||||
if(!frames) {
|
||||
DLog(@"Returning 0");
|
||||
return 0;
|
||||
return nil;
|
||||
}
|
||||
|
||||
int n = [decoder readAudio:buf frames:frames];
|
||||
AudioChunk *chunk = [decoder readAudio];
|
||||
|
||||
framePosition += n;
|
||||
size_t n = chunk.frameCount;
|
||||
if(n > frames) {
|
||||
[chunk setFrameCount:frames];
|
||||
}
|
||||
|
||||
return n;
|
||||
framePosition += chunk.frameCount;
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
- (BOOL)isSilence {
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
089C1672FE841209C02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
|
||||
089C167FFE841241C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
|
||||
1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
|
||||
834A42B3287AF65000EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
8352D48E1CDDB023009D16AA /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
|
||||
8352D4901CDDB02A009D16AA /* VideoDecodeAcceleration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = VideoDecodeAcceleration.framework; path = System/Library/Frameworks/VideoDecodeAcceleration.framework; sourceTree = SDKROOT; };
|
||||
8352D4921CDDB034009D16AA /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
|
||||
|
@ -145,6 +146,7 @@
|
|||
08FB77AFFE84173DC02AAC07 /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42B3287AF65000EB9D9B /* AudioChunk.h */,
|
||||
8356BD1A27B3D06F0074E50C /* HTTPSource.h */,
|
||||
8356BCEA27B37DA40074E50C /* TagLibID3v2Reader.h */,
|
||||
8356BCE827B37C6F0074E50C /* NSDictionary+Merge.h */,
|
||||
|
|
|
@ -45,8 +45,7 @@ int64_t ffmpeg_seek(void *opaque, int64_t offset, int whence);
|
|||
|
||||
BOOL metadataUpdated;
|
||||
|
||||
int prebufferedAudio;
|
||||
uint8_t *prebufferedAudioData;
|
||||
AudioChunk *prebufferedChunk;
|
||||
|
||||
BOOL rawDSD;
|
||||
BOOL rawDSDReverseBits;
|
||||
|
|
|
@ -471,13 +471,10 @@ static uint8_t reverse_bits[0x100];
|
|||
metadataUpdated = NO;
|
||||
[self updateMetadata];
|
||||
|
||||
prebufferedAudio = 0;
|
||||
prebufferedAudioData = NULL;
|
||||
prebufferedChunk = nil;
|
||||
|
||||
if(attachedPicIndex >= 0) {
|
||||
int frameSize = rawDSD ? channels : channels * (bitsPerSample / 8);
|
||||
prebufferedAudioData = malloc(1024 * frameSize);
|
||||
[self readAudio:prebufferedAudioData frames:1024];
|
||||
prebufferedChunk = [self readAudio];
|
||||
}
|
||||
|
||||
return YES;
|
||||
|
@ -681,30 +678,31 @@ static void setDictionary(NSMutableDictionary *dict, NSString *tag, NSString *va
|
|||
}
|
||||
}
|
||||
|
||||
- (int)readAudio:(void *)buf frames:(UInt32)frames {
|
||||
- (AudioChunk *)readAudio {
|
||||
if(!seekedToStart) {
|
||||
[self seek:0];
|
||||
}
|
||||
|
||||
if(prebufferedChunk) {
|
||||
// A bit of ignored read-ahead to support embedded artwork
|
||||
size_t framesReadNow = prebufferedChunk.frameCount;
|
||||
framesRead -= framesReadNow;
|
||||
AudioChunk *chunk = prebufferedChunk;
|
||||
prebufferedChunk = nil;
|
||||
return chunk;
|
||||
}
|
||||
|
||||
if(totalFrames && framesRead >= totalFrames)
|
||||
return nil;
|
||||
|
||||
int frames = 1024;
|
||||
|
||||
int frameSize = rawDSD ? channels : channels * (bitsPerSample / 8);
|
||||
int bytesToRead = frames * frameSize;
|
||||
int bytesRead = 0;
|
||||
|
||||
if(prebufferedAudio) {
|
||||
// A bit of ignored read-ahead to support embedded artwork
|
||||
int bytesBuffered = prebufferedAudio * frameSize;
|
||||
int bytesToCopy = (bytesBuffered > bytesToRead) ? bytesToRead : bytesBuffered;
|
||||
memcpy(buf, prebufferedAudioData, bytesToCopy);
|
||||
memmove(prebufferedAudioData, prebufferedAudioData + bytesToCopy, bytesBuffered - bytesToCopy);
|
||||
prebufferedAudio -= bytesToCopy / frameSize;
|
||||
bytesRead = bytesToCopy;
|
||||
|
||||
int framesReadNow = bytesRead / frameSize;
|
||||
framesRead -= framesReadNow;
|
||||
}
|
||||
|
||||
if(totalFrames && framesRead >= totalFrames)
|
||||
return 0;
|
||||
uint8_t buffer[bytesToRead];
|
||||
void *buf = (void *)buffer;
|
||||
|
||||
int dataSize = 0;
|
||||
|
||||
|
@ -909,7 +907,11 @@ static void setDictionary(NSMutableDictionary *dict, NSString *tag, NSString *va
|
|||
|
||||
framesRead += framesReadNow;
|
||||
|
||||
return framesReadNow;
|
||||
id audioChunkClass = NSClassFromString(@"AudioChunk");
|
||||
AudioChunk *chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
|
||||
[chunk assignSamples:buffer frameCount:framesReadNow];
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
- (long)seek:(long)frame {
|
||||
|
@ -918,7 +920,7 @@ static void setDictionary(NSMutableDictionary *dict, NSString *tag, NSString *va
|
|||
|
||||
seekedToStart = YES;
|
||||
|
||||
prebufferedAudio = 0;
|
||||
prebufferedChunk = nil;
|
||||
|
||||
if(frame >= totalFrames) {
|
||||
framesRead = totalFrames;
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
32DBCF630370AF2F00C91783 /* FileSource_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileSource_Prefix.pch; sourceTree = "<group>"; };
|
||||
8307D31B2860722C000FF8EB /* SandboxBroker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SandboxBroker.h; path = ../../Utils/SandboxBroker.h; sourceTree = "<group>"; };
|
||||
8335FF6817FF765A002D8DD2 /* File_Extractor.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = File_Extractor.xcodeproj; path = ../../Frameworks/File_Extractor/File_Extractor.xcodeproj; sourceTree = "<group>"; };
|
||||
834A42AD287AF25600EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
83747C4F2862DD2F0021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
|
||||
8D5B49B6048680CD000E48DA /* FileSource.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FileSource.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8D5B49B7048680CD000E48DA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
|
@ -91,6 +92,7 @@
|
|||
08FB77AFFE84173DC02AAC07 /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42AD287AF25600EB9D9B /* AudioChunk.h */,
|
||||
8307D31B2860722C000FF8EB /* SandboxBroker.h */,
|
||||
17ADB4080B979A8A00257CA2 /* Plugin.h */,
|
||||
17ADB4180B979AEB00257CA2 /* FileSource.h */,
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
32DBCF630370AF2F00C91783 /* Flac_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Flac_Prefix.pch; sourceTree = "<group>"; };
|
||||
8301C145287805F500651A6E /* NSDictionary+Merge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSDictionary+Merge.h"; path = "../../Utils/NSDictionary+Merge.h"; sourceTree = "<group>"; };
|
||||
8301C146287805F500651A6E /* NSDictionary+Merge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSDictionary+Merge.m"; path = "../../Utils/NSDictionary+Merge.m"; sourceTree = "<group>"; };
|
||||
834A42B4287AF7AA00EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
8356BD1927B3CCBB0074E50C /* HTTPSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTTPSource.h; path = ../HTTPSource/HTTPSource.h; sourceTree = "<group>"; };
|
||||
836EF0D927BB970B00BF35B2 /* libFLAC.8.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libFLAC.8.dylib; path = ../../ThirdParty/flac/lib/libFLAC.8.dylib; sourceTree = "<group>"; };
|
||||
83747C4A2862DCF40021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
|
||||
|
@ -92,6 +93,7 @@
|
|||
08FB77AFFE84173DC02AAC07 /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42B4287AF7AA00EB9D9B /* AudioChunk.h */,
|
||||
8301C145287805F500651A6E /* NSDictionary+Merge.h */,
|
||||
8301C146287805F500651A6E /* NSDictionary+Merge.m */,
|
||||
83AA660A27B7DAE40098D4B8 /* cuesheet.m */,
|
||||
|
|
|
@ -361,39 +361,23 @@ void ErrorCallback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorS
|
|||
return YES;
|
||||
}
|
||||
|
||||
- (int)readAudio:(void *)buffer frames:(UInt32)frames {
|
||||
int framesRead = 0;
|
||||
while(framesRead < frames) {
|
||||
if(blockBufferFrames == 0) {
|
||||
if(framesRead) {
|
||||
break;
|
||||
}
|
||||
- (AudioChunk *)readAudio {
|
||||
id audioChunkClass = NSClassFromString(@"AudioChunk");
|
||||
AudioChunk *chunk = nil;
|
||||
|
||||
if(FLAC__stream_decoder_get_state(decoder) == FLAC__STREAM_DECODER_END_OF_STREAM) {
|
||||
break;
|
||||
}
|
||||
if(FLAC__stream_decoder_get_state(decoder) == FLAC__STREAM_DECODER_END_OF_STREAM) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
if(!FLAC__stream_decoder_process_single(decoder)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!FLAC__stream_decoder_process_single(decoder)) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
int bytesPerFrame = ((bitsPerSample + 7) / 8) * channels;
|
||||
if(blockBufferFrames > 0) {
|
||||
chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
|
||||
[chunk assignSamples:blockBuffer frameCount:blockBufferFrames];
|
||||
|
||||
int framesToRead = blockBufferFrames;
|
||||
if(blockBufferFrames > frames) {
|
||||
framesToRead = frames;
|
||||
}
|
||||
|
||||
memcpy(((uint8_t *)buffer) + (framesRead * bytesPerFrame), (uint8_t *)blockBuffer, framesToRead * bytesPerFrame);
|
||||
|
||||
frames -= framesToRead;
|
||||
framesRead += framesToRead;
|
||||
blockBufferFrames -= framesToRead;
|
||||
|
||||
if(blockBufferFrames > 0) {
|
||||
memmove((uint8_t *)blockBuffer, ((uint8_t *)blockBuffer) + (framesToRead * bytesPerFrame), blockBufferFrames * bytesPerFrame);
|
||||
}
|
||||
blockBufferFrames = 0;
|
||||
}
|
||||
|
||||
if(![source seekable]) {
|
||||
|
@ -429,7 +413,7 @@ void ErrorCallback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorS
|
|||
}
|
||||
}
|
||||
|
||||
return framesRead;
|
||||
return chunk;
|
||||
}
|
||||
|
||||
- (void)close {
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
8319C74E237629D300BFFAE0 /* GamePropertiesReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GamePropertiesReader.h; sourceTree = "<group>"; };
|
||||
8319C74F237629D400BFFAE0 /* GamePropertiesReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GamePropertiesReader.m; sourceTree = "<group>"; };
|
||||
833F68351CDBCAB200AFB9F0 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
834A42B5287AF8FE00EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
835C888F22CC1883001B4B3F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
83747C452862DCD90021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
|
||||
8384912E1808175400E7332D /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logging.h; path = ../../Utils/Logging.h; sourceTree = "<group>"; };
|
||||
|
@ -119,6 +120,7 @@
|
|||
08FB77AFFE84173DC02AAC07 /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42B5287AF8FE00EB9D9B /* AudioChunk.h */,
|
||||
17C8F33B0CBED3BE008D969D /* GameContainer.h */,
|
||||
17C8F33C0CBED3BE008D969D /* GameContainer.m */,
|
||||
17C8F33D0CBED3BE008D969D /* GameDecoder.h */,
|
||||
|
|
|
@ -174,11 +174,18 @@ gme_err_t readCallback(void *data, void *out, int count) {
|
|||
return @{};
|
||||
}
|
||||
|
||||
- (int)readAudio:(void *)buf frames:(UInt32)frames {
|
||||
- (AudioChunk *)readAudio {
|
||||
int frames = 1024;
|
||||
int16_t buffer[frames * 2];
|
||||
void *buf = (void *)buffer;
|
||||
|
||||
id audioChunkClass = NSClassFromString(@"AudioChunk");
|
||||
AudioChunk *chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
|
||||
|
||||
int numSamples = frames * 2; // channels = 2
|
||||
|
||||
if(gme_track_ended(emu)) {
|
||||
return 0;
|
||||
return nil;
|
||||
}
|
||||
|
||||
if(IsRepeatOneSet())
|
||||
|
@ -190,7 +197,11 @@ gme_err_t readCallback(void *data, void *out, int count) {
|
|||
|
||||
// Some formats support length, but we'll add that in the future.
|
||||
//(From gme.txt) If track length, then use it. If loop length, play for intro + loop * 2. Otherwise, default to 2.5 minutes
|
||||
return frames; // GME will always generate samples. There's no real EOS.
|
||||
// GME will always generate samples. There's no real EOS.
|
||||
|
||||
[chunk assignSamples:buffer frameCount:numSamples];
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
- (long)seek:(long)frame {
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
17ADB60C0B97A74800257CA2 /* HTTPSource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HTTPSource.h; sourceTree = "<group>"; };
|
||||
17ADB6340B97A8B400257CA2 /* Plugin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Plugin.h; path = ../../Audio/Plugin.h; sourceTree = SOURCE_ROOT; };
|
||||
32DBCF630370AF2F00C91783 /* HTTPSource_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTTPSource_Prefix.pch; sourceTree = "<group>"; };
|
||||
834A42B9287AFAB500EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
8356BD1727B3B7340074E50C /* libcurl.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcurl.tbd; path = usr/lib/libcurl.tbd; sourceTree = SDKROOT; };
|
||||
83747C362862DC0D0021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
|
||||
8384912F1808180000E7332D /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logging.h; path = ../../Utils/Logging.h; sourceTree = "<group>"; };
|
||||
|
@ -87,6 +88,7 @@
|
|||
08FB77AFFE84173DC02AAC07 /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42B9287AFAB500EB9D9B /* AudioChunk.h */,
|
||||
8384912F1808180000E7332D /* Logging.h */,
|
||||
17ADB6340B97A8B400257CA2 /* Plugin.h */,
|
||||
17ADB60C0B97A74800257CA2 /* HTTPSource.h */,
|
||||
|
|
|
@ -190,6 +190,7 @@
|
|||
8343790C17F96E2600584396 /* HighlyQuixotic.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = HighlyQuixotic.xcodeproj; path = ../../Frameworks/HighlyQuixotic/HighlyQuixotic.xcodeproj; sourceTree = "<group>"; };
|
||||
8343796317F97BDB00584396 /* HighlyAdvanced.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = HighlyAdvanced.xcodeproj; path = ../../Frameworks/HighlyAdvanced/HighlyAdvanced.xcodeproj; sourceTree = "<group>"; };
|
||||
834379A717F9818400584396 /* HCDecoder.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = HCDecoder.mm; sourceTree = "<group>"; };
|
||||
834A42B6287AF99600EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
8360EEE417F92AC8005208A4 /* HighlyComplete.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HighlyComplete.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8360EEE717F92AC8005208A4 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
|
||||
8360EEEA17F92AC8005208A4 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
|
@ -311,6 +312,7 @@
|
|||
8360EEED17F92AC8005208A4 /* HighlyComplete */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42B6287AF99600EB9D9B /* AudioChunk.h */,
|
||||
83AA660827B7CCB00098D4B8 /* Logging.h */,
|
||||
83FAF8A318ADD27F00057CAF /* PlaylistController.h */,
|
||||
8324C584181513A10046F78F /* circular_buffer.h */,
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
- (psf_file_container *)init {
|
||||
if((self = [super init])) {
|
||||
lock = [[NSLock alloc] init];
|
||||
list = [[NSMutableDictionary alloc] initWithCapacity:0];
|
||||
list = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -1302,7 +1302,7 @@ static int usf_info(void *context, const char *name, const char *value) {
|
|||
return frames;
|
||||
}
|
||||
|
||||
- (int)readAudio:(void *)buf frames:(UInt32)frames {
|
||||
- (AudioChunk *)readAudio {
|
||||
if(!emulatorCore) {
|
||||
if(![self initializeDecoder])
|
||||
return 0;
|
||||
|
@ -1314,6 +1314,10 @@ static int usf_info(void *context, const char *name, const char *value) {
|
|||
usfRemoveSilence = NO;
|
||||
}
|
||||
|
||||
int frames = 1024;
|
||||
int16_t buffer[frames * 2];
|
||||
void *buf = (void *)buffer;
|
||||
|
||||
unsigned long written = silence_test_buffer.data_available() / 2;
|
||||
if(written > frames)
|
||||
written = frames;
|
||||
|
@ -1342,7 +1346,11 @@ static int usf_info(void *context, const char *name, const char *value) {
|
|||
|
||||
framesRead += written;
|
||||
|
||||
return (int)written;
|
||||
id audioChunkClass = NSClassFromString(@"AudioChunk");
|
||||
AudioChunk *chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
|
||||
[chunk assignSamples:buffer frameCount:written];
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
- (void)closeDecoder {
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
/* Begin PBXFileReference section */
|
||||
831C7F6918ADD73F00CE4A69 /* PlaylistController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlaylistController.h; path = ../../../Playlist/PlaylistController.h; sourceTree = "<group>"; };
|
||||
833F68471CDBCABF00AFB9F0 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
834A42B8287AFA3600EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
836FB52D1820538700B3AD2D /* Hively.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Hively.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
836FB5301820538700B3AD2D /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
|
||||
836FB5331820538700B3AD2D /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
|
@ -122,6 +123,7 @@
|
|||
836FB5361820538700B3AD2D /* Hively */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42B8287AFA3600EB9D9B /* AudioChunk.h */,
|
||||
831C7F6918ADD73F00CE4A69 /* PlaylistController.h */,
|
||||
836FB5A31820557E00B3AD2D /* Plugin.h */,
|
||||
836FB59A1820556F00B3AD2D /* HVLDecoder.h */,
|
||||
|
|
|
@ -107,7 +107,11 @@ static void oneTimeInit(void) {
|
|||
return @{};
|
||||
}
|
||||
|
||||
- (int)readAudio:(void *)buf frames:(UInt32)frames {
|
||||
- (AudioChunk *)readAudio {
|
||||
int frames = 1024;
|
||||
float buffer[frames * 2];
|
||||
void *buf = (void *)buffer;
|
||||
|
||||
BOOL repeatone = IsRepeatOneSet();
|
||||
|
||||
if(!repeatone && framesRead >= totalFrames)
|
||||
|
@ -157,7 +161,11 @@ static void oneTimeInit(void) {
|
|||
|
||||
framesRead += total;
|
||||
|
||||
return total;
|
||||
id audioChunkClass = NSClassFromString(@"AudioChunk");
|
||||
AudioChunk *chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
|
||||
[chunk assignSamples:buffer frameCount:total];
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
- (long)seek:(long)frame {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
|
||||
32DBCF630370AF2F00C91783 /* M3u_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = M3u_Prefix.pch; sourceTree = "<group>"; };
|
||||
833F68391CDBCAB200AFB9F0 /* es */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
834A42BA287AFAEF00EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
835C889122CC1885001B4B3F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
83747C2C2862DBBE0021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
|
||||
83849130180818B100E7332D /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logging.h; path = ../../Utils/Logging.h; sourceTree = "<group>"; };
|
||||
|
@ -75,6 +76,7 @@
|
|||
08FB77AFFE84173DC02AAC07 /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42BA287AFAEF00EB9D9B /* AudioChunk.h */,
|
||||
83849130180818B100E7332D /* Logging.h */,
|
||||
8E8D401B0CBAFEF200135C1B /* Plugin.h */,
|
||||
8E8D40270CBAFF4300135C1B /* M3uContainer.h */,
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
834A42BB287AFB0700EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
8372C92327C785BD00E250C9 /* MAD.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MAD.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8372C93327C7861300E250C9 /* MADDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MADDecoder.h; sourceTree = "<group>"; };
|
||||
8372C93427C7861300E250C9 /* MADDecoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MADDecoder.m; sourceTree = "<group>"; };
|
||||
|
@ -48,6 +49,7 @@
|
|||
children = (
|
||||
83747C262862DB9F0021245F /* Xcode-config */,
|
||||
83F97B6628600F9300A70B97 /* ThirdParty */,
|
||||
834A42BB287AFB0700EB9D9B /* AudioChunk.h */,
|
||||
8372C93A27C786DD00E250C9 /* HTTPSource.h */,
|
||||
8372C93927C7866B00E250C9 /* Logging.h */,
|
||||
8372C93827C7865A00E250C9 /* Plugin.h */,
|
||||
|
|
|
@ -651,7 +651,7 @@
|
|||
return 1;
|
||||
}
|
||||
|
||||
- (BOOL)syncFormat:(BOOL)updateNow {
|
||||
- (BOOL)syncFormat {
|
||||
float _sampleRate = _frame.header.samplerate;
|
||||
int _channels = MAD_NCHANNELS(&_frame.header);
|
||||
int _layer = 3;
|
||||
|
@ -674,7 +674,7 @@
|
|||
_channels != channels ||
|
||||
_layer != layer);
|
||||
|
||||
if(changed && updateNow) {
|
||||
if(changed) {
|
||||
sampleRate = _sampleRate;
|
||||
channels = _channels;
|
||||
layer = _layer;
|
||||
|
@ -686,29 +686,24 @@
|
|||
return changed;
|
||||
}
|
||||
|
||||
- (int)readAudio:(void *)buffer frames:(UInt32)frames {
|
||||
- (AudioChunk *)readAudio {
|
||||
int framesRead = 0;
|
||||
|
||||
if(!_firstFrame)
|
||||
[self syncFormat:YES];
|
||||
[self syncFormat];
|
||||
|
||||
id audioChunkClass = NSClassFromString(@"AudioChunk");
|
||||
AudioChunk *chunk = nil;
|
||||
|
||||
for(;;) {
|
||||
long framesRemaining = frames - framesRead;
|
||||
long framesToCopy = (_outputFrames > framesRemaining ? framesRemaining : _outputFrames);
|
||||
long framesToCopy = _outputFrames;
|
||||
|
||||
if(framesToCopy) {
|
||||
memcpy(buffer + (framesRead * channels * sizeof(float)), _outputBuffer, framesToCopy * channels * sizeof(float));
|
||||
framesRead += framesToCopy;
|
||||
|
||||
if(framesToCopy != _outputFrames) {
|
||||
memmove(_outputBuffer, _outputBuffer + (framesToCopy * channels), (_outputFrames - framesToCopy) * channels * sizeof(float));
|
||||
}
|
||||
|
||||
_outputFrames -= framesToCopy;
|
||||
}
|
||||
|
||||
if(framesRead == frames)
|
||||
chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
|
||||
[chunk assignSamples:_outputBuffer frameCount:framesToCopy];
|
||||
_outputFrames = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
int r = [self decodeMPEGFrame];
|
||||
// DLog(@"Decoding frame: %i", r);
|
||||
|
@ -720,18 +715,13 @@
|
|||
[self writeOutput];
|
||||
// DLog(@"Wrote output");
|
||||
|
||||
if([self syncFormat:NO]) {
|
||||
if(framesRead)
|
||||
break;
|
||||
else
|
||||
[self syncFormat:YES];
|
||||
}
|
||||
[self syncFormat];
|
||||
}
|
||||
|
||||
[self updateMetadata];
|
||||
|
||||
// DLog(@"Read: %i/%i", bytesRead, size);
|
||||
return framesRead;
|
||||
return chunk;
|
||||
}
|
||||
|
||||
- (void)close {
|
||||
|
|
|
@ -99,6 +99,7 @@
|
|||
831E2A9427B4B2FA006F1C86 /* json.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json.h; sourceTree = "<group>"; };
|
||||
831E2A9527B4B2FA006F1C86 /* json-builder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "json-builder.h"; sourceTree = "<group>"; };
|
||||
833F68431CDBCABE00AFB9F0 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
834A42BC287AFC7F00EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
834BE9191DE407CB00A07DCD /* resampler.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = resampler.c; sourceTree = "<group>"; };
|
||||
834BE91A1DE407CB00A07DCD /* resampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resampler.h; sourceTree = "<group>"; };
|
||||
8356BCC427B352620074E50C /* BMPlayer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BMPlayer.cpp; sourceTree = "<group>"; };
|
||||
|
@ -306,6 +307,7 @@
|
|||
83B06690180D5668008E3612 /* MIDI */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42BC287AFC7F00EB9D9B /* AudioChunk.h */,
|
||||
8307D31E28607377000FF8EB /* SandboxBroker.h */,
|
||||
831E2A9127B4B2FA006F1C86 /* json */,
|
||||
831E2A7D27B4B2B2006F1C86 /* BASS */,
|
||||
|
|
|
@ -276,14 +276,14 @@ static OSType getOSType(const char *in_) {
|
|||
return YES;
|
||||
}
|
||||
|
||||
- (int)readAudio:(void *)buf frames:(UInt32)frames {
|
||||
- (AudioChunk *)readAudio {
|
||||
BOOL repeatone = IsRepeatOneSet();
|
||||
long localFramesLength = framesLength;
|
||||
long localTotalFrames = totalFrames;
|
||||
|
||||
if(!player) {
|
||||
if(![self initDecoder])
|
||||
return -1;
|
||||
return nil;
|
||||
}
|
||||
|
||||
player->setLoopMode((repeatone || isLooped) ? (MIDIPlayer::loop_mode_enable | MIDIPlayer::loop_mode_force) : 0);
|
||||
|
@ -302,7 +302,10 @@ static OSType getOSType(const char *in_) {
|
|||
soundFontsAssigned = YES;
|
||||
}
|
||||
|
||||
UInt32 frames_done = player->Play((float *)buf, frames);
|
||||
int frames = 1024;
|
||||
float buffer[frames * 2];
|
||||
|
||||
UInt32 frames_done = player->Play(buffer, frames);
|
||||
|
||||
if(!frames_done)
|
||||
return 0;
|
||||
|
@ -315,7 +318,7 @@ static OSType getOSType(const char *in_) {
|
|||
long fadeEnd = (framesRead + frames > localTotalFrames) ? localTotalFrames : (framesRead + frames);
|
||||
long fadePos;
|
||||
|
||||
float *buff = (float *)buf;
|
||||
float *buff = buffer;
|
||||
|
||||
float fadeScale = (float)(framesFade - (fadeStart - localFramesLength)) / framesFade;
|
||||
float fadeStep = 1.0 / (float)framesFade;
|
||||
|
@ -337,13 +340,17 @@ static OSType getOSType(const char *in_) {
|
|||
}
|
||||
|
||||
framesRead += frames;
|
||||
return frames;
|
||||
|
||||
id audioChunkClass = NSClassFromString(@"AudioChunk");
|
||||
AudioChunk *chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
|
||||
[chunk assignSamples:buffer frameCount:frames];
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
- (long)seek:(long)frame {
|
||||
if(!player) {
|
||||
float temp[2];
|
||||
if([self readAudio:temp frames:1] < 1)
|
||||
if(![self readAudio])
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
1703330A0B8FB64500327265 /* MusepackDecoder.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = MusepackDecoder.m; sourceTree = "<group>"; };
|
||||
17F562570C3BD97B0019975C /* MPCDec.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = MPCDec.xcodeproj; path = ../../Frameworks/MPCDec/MPCDec.xcodeproj; sourceTree = SOURCE_ROOT; };
|
||||
32DBCF630370AF2F00C91783 /* Musepack_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Musepack_Prefix.pch; sourceTree = "<group>"; };
|
||||
834A42BD287AFD0D00EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
83747C1D2862DB560021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
|
||||
838491311808190400E7332D /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logging.h; path = ../../Utils/Logging.h; sourceTree = "<group>"; };
|
||||
8D5B49B6048680CD000E48DA /* Musepack.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Musepack.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
|
@ -105,6 +106,7 @@
|
|||
08FB77AFFE84173DC02AAC07 /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42BD287AFD0D00EB9D9B /* AudioChunk.h */,
|
||||
838491311808190400E7332D /* Logging.h */,
|
||||
8E2B8B4A0B9B48D000F2D9E8 /* Plugin.h */,
|
||||
170333090B8FB64500327265 /* MusepackDecoder.h */,
|
||||
|
|
|
@ -109,11 +109,15 @@ mpc_bool_t CanSeekProc(mpc_reader *p_reader) {
|
|||
return YES;
|
||||
}
|
||||
|
||||
- (int)readAudio:(void *)buf frames:(UInt32)frames {
|
||||
- (AudioChunk *)readAudio {
|
||||
MPC_SAMPLE_FORMAT sampleBuffer[MPC_DECODER_BUFFER_LENGTH];
|
||||
|
||||
int frames = 1024;
|
||||
float buffer[frames * 2];
|
||||
void *buf = (void *)buffer;
|
||||
|
||||
int framesRead = 0;
|
||||
int bytesPerFrame = sizeof(float) * 2; // bitsPerSample == 16, channels == 2
|
||||
int bytesPerFrame = sizeof(float) * 2; // bitsPerSample == 32, channels == 2
|
||||
while(framesRead < frames) {
|
||||
// Fill from buffer, going by bufferFrames
|
||||
// if still needs more, decode and repeat
|
||||
|
@ -150,7 +154,11 @@ mpc_bool_t CanSeekProc(mpc_reader *p_reader) {
|
|||
}
|
||||
}
|
||||
|
||||
return framesRead;
|
||||
id audioChunkClass = NSClassFromString(@"AudioChunk");
|
||||
AudioChunk *chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
|
||||
[chunk assignSamples:buffer frameCount:framesRead];
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
- (void)close {
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
|
||||
/* Begin PBXFileReference section */
|
||||
833A899B286FF3150022E036 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
|
||||
834A42BE287AFDC300EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
83747C182862DB2F0021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
|
||||
83E5EFA31FFEF78100659F0F /* OpenMPT.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OpenMPT.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
83E5EFA61FFEF78100659F0F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
|
@ -124,6 +125,7 @@
|
|||
83E5FE6A1FFF003900659F0F /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42BE287AFDC300EB9D9B /* AudioChunk.h */,
|
||||
83E5FE6B1FFF004D00659F0F /* Logging.h */,
|
||||
83E5FE761FFF076F00659F0F /* PlaylistController.h */,
|
||||
83E5FE6C1FFF006400659F0F /* Plugin.h */,
|
||||
|
|
|
@ -112,9 +112,13 @@ static void g_push_archive_extensions(std::vector<std::string> &list) {
|
|||
return @{};
|
||||
}
|
||||
|
||||
- (int)readAudio:(void *)buf frames:(UInt32)frames {
|
||||
- (AudioChunk *)readAudio {
|
||||
mod->set_repeat_count(IsRepeatOneSet() ? -1 : 0);
|
||||
|
||||
int frames = 1024;
|
||||
float buffer[frames * 2];
|
||||
void *buf = (void *)buffer;
|
||||
|
||||
int total = 0;
|
||||
while(total < frames) {
|
||||
int framesToRender = 1024;
|
||||
|
@ -131,7 +135,11 @@ static void g_push_archive_extensions(std::vector<std::string> &list) {
|
|||
break;
|
||||
}
|
||||
|
||||
return total;
|
||||
id audioChunkClass = NSClassFromString(@"AudioChunk");
|
||||
AudioChunk *chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
|
||||
[chunk assignSamples:buffer frameCount:total];
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
- (long)seek:(long)frame {
|
||||
|
|
|
@ -222,7 +222,7 @@ static void setDictionary(NSMutableDictionary *dict, NSString *tag, NSString *va
|
|||
}
|
||||
}
|
||||
|
||||
- (int)readAudio:(void *)buf frames:(UInt32)frames {
|
||||
- (AudioChunk *)readAudio {
|
||||
int numread;
|
||||
int total = 0;
|
||||
|
||||
|
@ -236,7 +236,10 @@ static void setDictionary(NSMutableDictionary *dict, NSString *tag, NSString *va
|
|||
[self updateMetadata];
|
||||
}
|
||||
|
||||
int frames = 1024;
|
||||
int size = frames * channels;
|
||||
float buffer[size];
|
||||
void *buf = (void *)buffer;
|
||||
|
||||
do {
|
||||
float *out = ((float *)buf) + total;
|
||||
|
@ -265,7 +268,11 @@ static void setDictionary(NSMutableDictionary *dict, NSString *tag, NSString *va
|
|||
|
||||
[self updateIcyMetadata];
|
||||
|
||||
return total / channels;
|
||||
id audioChunkClass = NSClassFromString(@"AudioChunk");
|
||||
AudioChunk *chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
|
||||
[chunk assignSamples:buffer frameCount:total / channels];
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
- (void)close {
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
83186314285CEC91001422CC /* NSDictionary+Merge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSDictionary+Merge.h"; path = "../../../Utils/NSDictionary+Merge.h"; sourceTree = "<group>"; };
|
||||
83186315285CEC91001422CC /* NSDictionary+Merge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSDictionary+Merge.m"; path = "../../../Utils/NSDictionary+Merge.m"; sourceTree = "<group>"; };
|
||||
833F68411CDBCABC00AFB9F0 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
834A42BF287AFE2600EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
8356BD1B27B469B80074E50C /* HTTPSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTTPSource.h; path = ../../HTTPSource/HTTPSource.h; sourceTree = "<group>"; };
|
||||
836EF0CE27BB952F00BF35B2 /* libopusfile.0.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libopusfile.0.dylib; path = ../../ThirdParty/opusfile/lib/libopusfile.0.dylib; sourceTree = "<group>"; };
|
||||
83747C0E2862DAC70021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
|
||||
|
@ -114,6 +115,7 @@
|
|||
8375B04517FFEA400092A79F /* Opus */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42BF287AFE2600EB9D9B /* AudioChunk.h */,
|
||||
83186314285CEC91001422CC /* NSDictionary+Merge.h */,
|
||||
83186315285CEC91001422CC /* NSDictionary+Merge.m */,
|
||||
8356BD1B27B469B80074E50C /* HTTPSource.h */,
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
|
||||
32DBCF630370AF2F00C91783 /* Pls_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Pls_Prefix.pch; sourceTree = "<group>"; };
|
||||
833F68381CDBCAB200AFB9F0 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
834A42C0287AFEB100EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
835C889422CC1887001B4B3F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
83747C092862DAA90021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
|
||||
838491321808193F00E7332D /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logging.h; path = ../../Utils/Logging.h; sourceTree = "<group>"; };
|
||||
|
@ -75,6 +76,7 @@
|
|||
08FB77AFFE84173DC02AAC07 /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42C0287AFEB100EB9D9B /* AudioChunk.h */,
|
||||
838491321808193F00E7332D /* Logging.h */,
|
||||
8E8D41A50CBB0CBE00135C1B /* Plugin.h */,
|
||||
8E8D419F0CBB0CA700135C1B /* PlsContainer.h */,
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
177FCFAC0B90C96B0011C3B5 /* Plugin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Plugin.h; path = ../../Audio/Plugin.h; sourceTree = SOURCE_ROOT; };
|
||||
17F563DD0C3BDBF10019975C /* Shorten.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Shorten.xcodeproj; path = ../../Frameworks/Shorten/Shorten.xcodeproj; sourceTree = SOURCE_ROOT; };
|
||||
32DBCF630370AF2F00C91783 /* Shorten_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Shorten_Prefix.pch; sourceTree = "<group>"; };
|
||||
834A42A9287AEF1300EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
83747C042862DA780021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
|
||||
8D5B49B6048680CD000E48DA /* Shorten.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Shorten.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8D5B49B7048680CD000E48DA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
|
@ -104,6 +105,7 @@
|
|||
08FB77AFFE84173DC02AAC07 /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42A9287AEF1300EB9D9B /* AudioChunk.h */,
|
||||
177FCFAC0B90C96B0011C3B5 /* Plugin.h */,
|
||||
1745C42B0B90C1DC00A6768C /* ShortenDecoder.h */,
|
||||
1745C42C0B90C1DC00A6768C /* ShortenDecoder.mm */,
|
||||
|
|
|
@ -41,16 +41,25 @@
|
|||
return YES;
|
||||
}
|
||||
|
||||
- (int)readAudio:(void *)buf frames:(UInt32)frames {
|
||||
- (AudioChunk *)readAudio {
|
||||
long frames = 1024;
|
||||
long bytesPerFrame = channels * (bitsPerSample / 8);
|
||||
long amountRead;
|
||||
|
||||
id audioChunkClass = NSClassFromString(@"AudioChunk");
|
||||
AudioChunk *chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
|
||||
|
||||
uint8_t buffer[bytesPerFrame * 1024];
|
||||
void *buf = (void *)buffer;
|
||||
|
||||
// For some reason a busy loop is causing pops when output is set to 48000. Probably CPU starvation, since the SHN decoder seems to use a multithreaded nonblocking approach.
|
||||
do {
|
||||
amountRead = decoder->read(buf, frames * bytesPerFrame);
|
||||
} while(amountRead == -1);
|
||||
|
||||
return (int)(amountRead / bytesPerFrame);
|
||||
[chunk assignSamples:buf frameCount:amountRead / bytesPerFrame];
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
- (long)seek:(long)sample {
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
834A42C1287AFED700EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
83747BFA2862D95C0021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
|
||||
83F9D7E71A884B44007ABEC2 /* SilenceDecoder.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SilenceDecoder.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
83F9D7EB1A884B44007ABEC2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
|
@ -64,6 +65,7 @@
|
|||
83F9D7E91A884B44007ABEC2 /* SilenceDecoder */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42C1287AFED700EB9D9B /* AudioChunk.h */,
|
||||
83F9D8091A884CB5007ABEC2 /* Logging.h */,
|
||||
83F9D8081A884C93007ABEC2 /* Plugin.h */,
|
||||
83F9D8041A884C23007ABEC2 /* PlaylistController.h */,
|
||||
|
|
|
@ -50,7 +50,11 @@ enum { channels = 2 };
|
|||
return @{};
|
||||
}
|
||||
|
||||
- (int)readAudio:(void *)buf frames:(UInt32)frames {
|
||||
- (AudioChunk *)readAudio {
|
||||
int frames = 1024;
|
||||
float buffer[frames * channels];
|
||||
void *buf = (void *)buffer;
|
||||
|
||||
int total = frames;
|
||||
|
||||
if(!IsRepeatOneSet()) {
|
||||
|
@ -62,7 +66,11 @@ enum { channels = 2 };
|
|||
|
||||
memset(buf, 0, sizeof(float) * total * channels);
|
||||
|
||||
return total;
|
||||
id audioChunkClass = NSClassFromString(@"AudioChunk");
|
||||
AudioChunk *chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
|
||||
[chunk assignSamples:buffer frameCount:total];
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
- (long)seek:(long)frame {
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
17F563B40C3BDBB30019975C /* TagLib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17F563A60C3BDB8F0019975C /* TagLib.framework */; };
|
||||
17F563B60C3BDBB50019975C /* TagLib.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 17F563A60C3BDB8F0019975C /* TagLib.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
8307D31D286072BF000FF8EB /* SandboxBroker.h in Headers */ = {isa = PBXBuildFile; fileRef = 8307D31C286072BF000FF8EB /* SandboxBroker.h */; };
|
||||
834A42C3287AFF5E00EB9D9B /* AudioChunk.h in Headers */ = {isa = PBXBuildFile; fileRef = 834A42C2287AFF5E00EB9D9B /* AudioChunk.h */; };
|
||||
8356BCE527B377C20074E50C /* TagLibID3v2Reader.h in Headers */ = {isa = PBXBuildFile; fileRef = 8356BCE327B377C20074E50C /* TagLibID3v2Reader.h */; };
|
||||
8356BCE627B377C20074E50C /* TagLibID3v2Reader.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8356BCE427B377C20074E50C /* TagLibID3v2Reader.mm */; };
|
||||
8384913A18081FFC00E7332D /* Logging.h in Headers */ = {isa = PBXBuildFile; fileRef = 8384913918081FFC00E7332D /* Logging.h */; };
|
||||
|
@ -60,6 +61,7 @@
|
|||
17F563A00C3BDB8F0019975C /* TagLib.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = TagLib.xcodeproj; path = ../../Frameworks/TagLib/TagLib.xcodeproj; sourceTree = SOURCE_ROOT; };
|
||||
32DBCF630370AF2F00C91783 /* TagLib_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TagLib_Prefix.pch; sourceTree = "<group>"; };
|
||||
8307D31C286072BF000FF8EB /* SandboxBroker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SandboxBroker.h; path = ../../Utils/SandboxBroker.h; sourceTree = "<group>"; };
|
||||
834A42C2287AFF5E00EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
8356BCE327B377C20074E50C /* TagLibID3v2Reader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TagLibID3v2Reader.h; sourceTree = "<group>"; };
|
||||
8356BCE427B377C20074E50C /* TagLibID3v2Reader.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = TagLibID3v2Reader.mm; sourceTree = "<group>"; };
|
||||
83747BF52862D9470021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
|
||||
|
@ -115,6 +117,7 @@
|
|||
08FB77AFFE84173DC02AAC07 /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42C2287AFF5E00EB9D9B /* AudioChunk.h */,
|
||||
8307D31C286072BF000FF8EB /* SandboxBroker.h */,
|
||||
8384913918081FFC00E7332D /* Logging.h */,
|
||||
07CACE890ED1AD1000C0F1E8 /* TagLibMetadataWriter.h */,
|
||||
|
@ -188,6 +191,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8384913A18081FFC00E7332D /* Logging.h in Headers */,
|
||||
834A42C3287AFF5E00EB9D9B /* AudioChunk.h in Headers */,
|
||||
8307D31D286072BF000FF8EB /* SandboxBroker.h in Headers */,
|
||||
8356BCE527B377C20074E50C /* TagLibID3v2Reader.h in Headers */,
|
||||
);
|
||||
|
|
|
@ -200,9 +200,10 @@ static void setDictionary(NSMutableDictionary *dict, NSString *tag, NSString *va
|
|||
}
|
||||
}
|
||||
|
||||
- (int)readAudio:(void *)buf frames:(UInt32)frames {
|
||||
- (AudioChunk *)readAudio {
|
||||
int numread;
|
||||
int total = 0;
|
||||
int frames = 1024;
|
||||
|
||||
if(currentSection != lastSection) {
|
||||
vorbis_info *vi;
|
||||
|
@ -218,6 +219,12 @@ static void setDictionary(NSMutableDictionary *dict, NSString *tag, NSString *va
|
|||
[self updateMetadata];
|
||||
}
|
||||
|
||||
id audioChunkClass = NSClassFromString(@"AudioChunk");
|
||||
AudioChunk *chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
|
||||
|
||||
float buffer[frames * channels];
|
||||
void *buf = (void *)buffer;
|
||||
|
||||
do {
|
||||
lastSection = currentSection;
|
||||
float **pcm;
|
||||
|
@ -247,7 +254,9 @@ static void setDictionary(NSMutableDictionary *dict, NSString *tag, NSString *va
|
|||
|
||||
[self updateIcyMetadata];
|
||||
|
||||
return total;
|
||||
[chunk assignSamples:buffer frameCount:total];
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
- (void)close {
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
8301C14A287810F300651A6E /* libFLAC.8.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libFLAC.8.dylib; path = ../../ThirdParty/flac/lib/libFLAC.8.dylib; sourceTree = "<group>"; };
|
||||
83186311285CEBD2001422CC /* NSDictionary+Merge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSDictionary+Merge.h"; path = "../../Utils/NSDictionary+Merge.h"; sourceTree = "<group>"; };
|
||||
83186312285CEBD2001422CC /* NSDictionary+Merge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSDictionary+Merge.m"; path = "../../Utils/NSDictionary+Merge.m"; sourceTree = "<group>"; };
|
||||
834A42AB287AF0B000EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
8356BD1C27B46A2D0074E50C /* HTTPSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTTPSource.h; path = ../HTTPSource/HTTPSource.h; sourceTree = "<group>"; };
|
||||
836EF0D427BB969D00BF35B2 /* libvorbisfile.3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libvorbisfile.3.dylib; path = ../../ThirdParty/vorbis/lib/libvorbisfile.3.dylib; sourceTree = "<group>"; };
|
||||
836EF0DE27BB987000BF35B2 /* libvorbis.0.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libvorbis.0.dylib; path = ../../ThirdParty/vorbis/lib/libvorbis.0.dylib; sourceTree = "<group>"; };
|
||||
|
@ -92,6 +93,7 @@
|
|||
08FB77AFFE84173DC02AAC07 /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42AB287AF0B000EB9D9B /* AudioChunk.h */,
|
||||
83186311285CEBD2001422CC /* NSDictionary+Merge.h */,
|
||||
83186312285CEBD2001422CC /* NSDictionary+Merge.m */,
|
||||
8356BD1C27B46A2D0074E50C /* HTTPSource.h */,
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
177FCF940B90C9450011C3B5 /* Plugin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Plugin.h; path = ../../Audio/Plugin.h; sourceTree = SOURCE_ROOT; };
|
||||
17F562C20C3BDA5A0019975C /* WavPack.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = WavPack.xcodeproj; path = ../../Frameworks/WavPack/WavPack.xcodeproj; sourceTree = SOURCE_ROOT; };
|
||||
32DBCF630370AF2F00C91783 /* WavPack_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WavPack_Prefix.pch; sourceTree = "<group>"; };
|
||||
834A42AA287AEFC300EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
83747BE62862D8D60021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
|
||||
83849133180819EB00E7332D /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logging.h; path = ../../Utils/Logging.h; sourceTree = "<group>"; };
|
||||
8D5B49B6048680CD000E48DA /* WavPack.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = WavPack.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
|
@ -105,6 +106,7 @@
|
|||
08FB77AFFE84173DC02AAC07 /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42AA287AEFC300EB9D9B /* AudioChunk.h */,
|
||||
83849133180819EB00E7332D /* Logging.h */,
|
||||
177FCF940B90C9450011C3B5 /* Plugin.h */,
|
||||
1745C4D50B90C42500A6768C /* WavPackDecoder.h */,
|
||||
|
|
|
@ -196,7 +196,12 @@ int32_t WriteBytesProc(void *ds, void *data, int32_t bcount) {
|
|||
return n;
|
||||
}
|
||||
*/
|
||||
- (int)readAudio:(void *)buf frames:(UInt32)frames {
|
||||
- (AudioChunk *)readAudio {
|
||||
int32_t frames = 1024;
|
||||
|
||||
id audioChunkClass = NSClassFromString(@"AudioChunk");
|
||||
AudioChunk *chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
|
||||
|
||||
uint32_t sample;
|
||||
int32_t audioSample;
|
||||
uint32_t samplesRead;
|
||||
|
@ -204,6 +209,10 @@ int32_t WriteBytesProc(void *ds, void *data, int32_t bcount) {
|
|||
int16_t *alias16;
|
||||
int32_t *alias32;
|
||||
|
||||
const size_t bufferSize = frames * [chunk format].mBytesPerFrame;
|
||||
uint8_t buffer[bufferSize];
|
||||
void *buf = (void *)buffer;
|
||||
|
||||
size_t newSize = frames * sizeof(int32_t) * channels;
|
||||
if(!inputBuffer || newSize > inputBufferSize) {
|
||||
inputBuffer = realloc(inputBuffer, inputBufferSize = newSize);
|
||||
|
@ -248,7 +257,9 @@ int32_t WriteBytesProc(void *ds, void *data, int32_t bcount) {
|
|||
ALog(@"Unsupported sample size: %d", bitsPerSample);
|
||||
}
|
||||
|
||||
return samplesRead;
|
||||
[chunk assignSamples:buffer frameCount:samplesRead];
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
- (long)seek:(long)frame {
|
||||
|
|
|
@ -208,9 +208,18 @@ const int masterVol = 0x10000; // Fixed point 16.16
|
|||
return @{};
|
||||
}
|
||||
|
||||
- (int)readAudio:(void*)buf frames:(UInt32)frames {
|
||||
- (AudioChunk*)readAudio {
|
||||
if([self trackEnded])
|
||||
return 0;
|
||||
return nil;
|
||||
|
||||
id audioChunkClass = NSClassFromString(@"AudioChunk");
|
||||
AudioChunk* chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
|
||||
|
||||
int frames = 1024;
|
||||
const size_t bytesPerFrame = [chunk format].mBytesPerFrame;
|
||||
uint8_t buffer[frames * bytesPerFrame];
|
||||
|
||||
void* buf = (void*)buffer;
|
||||
|
||||
BOOL repeatOne = IsRepeatOneSet();
|
||||
uint32_t maxLoops = repeatOne ? 0 : (uint32_t)loopCount;
|
||||
|
@ -238,7 +247,9 @@ const int masterVol = 0x10000; // Fixed point 16.16
|
|||
framesDone += framesToDo;
|
||||
}
|
||||
|
||||
return framesDone;
|
||||
[chunk assignSamples:buffer frameCount:framesDone];
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
- (long)seek:(long)frame {
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
83489C602782F39D00BDCEA2 /* libvgm-player.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libvgm-player.a"; path = "../../ThirdParty/libvgm/lib/libvgm-player.a"; sourceTree = "<group>"; };
|
||||
83489C652782F74800BDCEA2 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
|
||||
83489C672782F74E00BDCEA2 /* libiconv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.tbd; path = usr/lib/libiconv.tbd; sourceTree = SDKROOT; };
|
||||
834A42AC287AF18E00EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
835C888F22CC1883001B4B3F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
83747C312862DBE80021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
|
||||
8384912E1808175400E7332D /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logging.h; path = ../../Utils/Logging.h; sourceTree = "<group>"; };
|
||||
|
@ -102,6 +103,7 @@
|
|||
08FB77AFFE84173DC02AAC07 /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42AC287AF18E00EB9D9B /* AudioChunk.h */,
|
||||
17C8F33B0CBED3BE008D969D /* libvgmContainer.h */,
|
||||
17C8F33C0CBED3BE008D969D /* libvgmContainer.mm */,
|
||||
17C8F33D0CBED3BE008D969D /* libvgmDecoder.h */,
|
||||
|
|
|
@ -62,7 +62,7 @@ static const char *extListStr[] = { ".str", NULL };
|
|||
- (sid_file_container *)init {
|
||||
if((self = [super init])) {
|
||||
lock = [[NSLock alloc] init];
|
||||
list = [[NSMutableDictionary alloc] initWithCapacity:0];
|
||||
list = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -275,59 +275,54 @@ static void sidTuneLoader(const char *fileName, std::vector<uint8_t> &bufferRef)
|
|||
return @{};
|
||||
}
|
||||
|
||||
- (int)readAudio:(void *)buf frames:(UInt32)frames {
|
||||
- (AudioChunk *)readAudio {
|
||||
int total = 0;
|
||||
int16_t *sampleBuffer = (int16_t *)buf;
|
||||
while(total < frames) {
|
||||
int framesToRender = 1024;
|
||||
if(framesToRender > frames)
|
||||
framesToRender = frames;
|
||||
int rendered = engine->play(sampleBuffer + total * n_channels, framesToRender * n_channels) / n_channels;
|
||||
id audioChunkClass = NSClassFromString(@"AudioChunk");
|
||||
AudioChunk *chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
|
||||
|
||||
if(rendered <= 0)
|
||||
break;
|
||||
int16_t buffer[1024 * n_channels];
|
||||
|
||||
if(n_channels == 2) {
|
||||
for(int i = 0, j = rendered * 2; i < j; i += 2) {
|
||||
int16_t *sample = sampleBuffer + total * 2 + i;
|
||||
int mid = (int)(sample[0] + sample[1]) / 2;
|
||||
int side = (int)(sample[0] - sample[1]) / 4;
|
||||
sample[0] = mid + side;
|
||||
sample[1] = mid - side;
|
||||
}
|
||||
int framesToRender = 1024;
|
||||
int rendered = engine->play(buffer, framesToRender * n_channels) / n_channels;
|
||||
|
||||
if(rendered <= 0)
|
||||
return nil;
|
||||
|
||||
if(n_channels == 2) {
|
||||
for(int i = 0, j = rendered * 2; i < j; i += 2) {
|
||||
int16_t *sample = buffer + total * 2 + i;
|
||||
int mid = (int)(sample[0] + sample[1]) / 2;
|
||||
int side = (int)(sample[0] - sample[1]) / 4;
|
||||
sample[0] = mid + side;
|
||||
sample[1] = mid - side;
|
||||
}
|
||||
|
||||
renderedTotal += rendered;
|
||||
|
||||
if(!IsRepeatOneSet() && renderedTotal >= length) {
|
||||
int16_t *sampleBuf = (int16_t *)buf + total * n_channels;
|
||||
long fadeEnd = fadeRemain - rendered;
|
||||
if(fadeEnd < 0)
|
||||
fadeEnd = 0;
|
||||
float fadePosf = (float)fadeRemain / (float)fadeTotal;
|
||||
const float fadeStep = 1.0f / (float)fadeTotal;
|
||||
for(long fadePos = fadeRemain; fadePos > fadeEnd; --fadePos, fadePosf -= fadeStep) {
|
||||
long offset = (fadeRemain - fadePos) * n_channels;
|
||||
float sampleLeft = sampleBuf[offset + 0];
|
||||
sampleLeft *= fadePosf;
|
||||
sampleBuf[offset + 0] = (int16_t)sampleLeft;
|
||||
if(n_channels == 2) {
|
||||
float sampleRight = sampleBuf[offset + 1];
|
||||
sampleRight *= fadePosf;
|
||||
sampleBuf[offset + 1] = (int16_t)sampleRight;
|
||||
}
|
||||
}
|
||||
rendered = (int)(fadeRemain - fadeEnd);
|
||||
fadeRemain = fadeEnd;
|
||||
}
|
||||
|
||||
total += rendered;
|
||||
|
||||
if(rendered < framesToRender)
|
||||
break;
|
||||
}
|
||||
|
||||
return total;
|
||||
if(!IsRepeatOneSet() && renderedTotal >= length) {
|
||||
int16_t *sampleBuf = buffer;
|
||||
long fadeEnd = fadeRemain - rendered;
|
||||
if(fadeEnd < 0)
|
||||
fadeEnd = 0;
|
||||
float fadePosf = (float)fadeRemain / (float)fadeTotal;
|
||||
const float fadeStep = 1.0f / (float)fadeTotal;
|
||||
for(long fadePos = fadeRemain; fadePos > fadeEnd; --fadePos, fadePosf -= fadeStep) {
|
||||
long offset = (fadeRemain - fadePos) * n_channels;
|
||||
float sampleLeft = sampleBuf[offset + 0];
|
||||
sampleLeft *= fadePosf;
|
||||
sampleBuf[offset + 0] = (int16_t)sampleLeft;
|
||||
if(n_channels == 2) {
|
||||
float sampleRight = sampleBuf[offset + 1];
|
||||
sampleRight *= fadePosf;
|
||||
sampleBuf[offset + 1] = (int16_t)sampleRight;
|
||||
}
|
||||
}
|
||||
rendered = (int)(fadeRemain - fadeEnd);
|
||||
fadeRemain = fadeEnd;
|
||||
}
|
||||
|
||||
[chunk assignSamples:buffer frameCount:rendered];
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
- (long)seek:(long)frame {
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
8314D80D1A35658C00EEE8E6 /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logging.h; path = ../../../Utils/Logging.h; sourceTree = "<group>"; };
|
||||
8314D80E1A3565AC00EEE8E6 /* PlaylistController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlaylistController.h; path = ../../../Playlist/PlaylistController.h; sourceTree = "<group>"; };
|
||||
833A8996286FF2E30022E036 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
|
||||
834A42A6287AEAAB00EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
836F5BEA1A357915002730CC /* roms.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = roms.cpp; sourceTree = SOURCE_ROOT; };
|
||||
836F5BEB1A357915002730CC /* roms.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = roms.hpp; sourceTree = SOURCE_ROOT; };
|
||||
83747BFF2862DA420021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
|
||||
|
@ -92,6 +93,7 @@
|
|||
8314D6331A354DFE00EEE8E6 /* sidplay */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
834A42A6287AEAAB00EB9D9B /* AudioChunk.h */,
|
||||
836F5BEA1A357915002730CC /* roms.cpp */,
|
||||
836F5BEB1A357915002730CC /* roms.hpp */,
|
||||
8314D80E1A3565AC00EEE8E6 /* PlaylistController.h */,
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
833F68491CDBCAC000AFB9F0 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
8340888B1F6F604A00DCD404 /* VGMMetadataReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VGMMetadataReader.m; sourceTree = "<group>"; };
|
||||
8340888D1F6F604B00DCD404 /* VGMMetadataReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VGMMetadataReader.h; sourceTree = "<group>"; };
|
||||
834A42A8287AEDFB00EB9D9B /* AudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioChunk.h; path = ../../../Audio/Chain/AudioChunk.h; sourceTree = "<group>"; };
|
||||
835D241E235AB318009A1251 /* VGMPropertiesReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VGMPropertiesReader.m; sourceTree = "<group>"; };
|
||||
835D241F235AB319009A1251 /* VGMPropertiesReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VGMPropertiesReader.h; sourceTree = "<group>"; };
|
||||
836F6B1018BDB80D0095E648 /* vgmstream.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = vgmstream.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
|
@ -141,6 +142,7 @@
|
|||
836F705A18BDC40E0095E648 /* VGMDecoder.h */,
|
||||
836F705B18BDC40E0095E648 /* VGMDecoder.m */,
|
||||
83AA5D2F1F6E301B0020821C /* Logging.h */,
|
||||
834A42A8287AEDFB00EB9D9B /* AudioChunk.h */,
|
||||
836F706018BDC84D0095E648 /* Plugin.h */,
|
||||
836F6B1A18BDB80D0095E648 /* Supporting Files */,
|
||||
);
|
||||
|
|
|
@ -311,10 +311,17 @@ static NSString *get_description_tag(const char *description, const char *tag, c
|
|||
return @{};
|
||||
}
|
||||
|
||||
- (int)readAudio:(void *)buf frames:(UInt32)frames {
|
||||
- (AudioChunk *)readAudio {
|
||||
UInt32 frames = 1024;
|
||||
UInt32 framesMax = frames;
|
||||
UInt32 framesDone = 0;
|
||||
|
||||
id audioChunkClass = NSClassFromString(@"AudioChunk");
|
||||
AudioChunk *chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
|
||||
|
||||
int16_t buffer[1024 * channels];
|
||||
void *buf = (void *)buffer;
|
||||
|
||||
if(canPlayForever) {
|
||||
BOOL repeatone = IsRepeatOneSet();
|
||||
|
||||
|
@ -354,7 +361,9 @@ static NSString *get_description_tag(const char *description, const char *tag, c
|
|||
frames -= frames_to_do;
|
||||
}
|
||||
|
||||
return framesDone;
|
||||
[chunk assignSamples:buffer frameCount:framesDone];
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
- (long)seek:(long)frame {
|
||||
|
|
Loading…
Reference in New Issue