Removed decoders folder.
parent
84e7b7df83
commit
656be855ce
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2006 Stephen F. Booth <me@sbooth.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include <AudioToolbox/ExtendedAudioFile.h>
|
||||
|
||||
#import "SoundFile.h"
|
||||
#undef _USE_WRAPPER_
|
||||
|
||||
@interface CoreAudioFile : SoundFile
|
||||
{
|
||||
ExtAudioFileRef _in;
|
||||
|
||||
#ifdef _USE_WRAPPER_
|
||||
int _inFd;
|
||||
AudioFileID _audioID;
|
||||
|
||||
SInt64 _fileSize;
|
||||
SInt64 _startOffset;
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,324 +0,0 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2006 Stephen F. Booth <me@sbooth.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#import "CoreAudioFile.h"
|
||||
|
||||
@interface CoreAudioFile (Private)
|
||||
- (BOOL) readInfoFromExtAudioFileRef;
|
||||
@end
|
||||
|
||||
@implementation CoreAudioFile
|
||||
|
||||
#ifdef _USE_WRAPPER_
|
||||
OSStatus readFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, void *buffer, ByteCount* actualCount)
|
||||
{
|
||||
CoreAudioFile *caf = (CoreAudioFile *)inRefCon;
|
||||
int fd = caf->_inFd;
|
||||
|
||||
// fseek(fd, inPosition, SEEK_SET);
|
||||
// NSLog(@"Requesting %u", requestCount);
|
||||
// NSLog(@"Currently at %lli", inPosition);
|
||||
|
||||
*actualCount = pread(fd, buffer, requestCount, inPosition+caf->_startOffset);
|
||||
|
||||
if (*actualCount <= 0)
|
||||
{
|
||||
return -1000; //Error?
|
||||
}
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
SInt64 getSizeFunc(void *inRefCon)
|
||||
{
|
||||
CoreAudioFile *caf = (CoreAudioFile *)inRefCon;
|
||||
int fd = caf->_inFd;
|
||||
|
||||
if (caf->_fileSize != 0)
|
||||
{
|
||||
return caf->_fileSize;
|
||||
}
|
||||
|
||||
/* long curPos;
|
||||
|
||||
curPos = ftell(fd);
|
||||
|
||||
fseek(fd, 0, SEEK_END);
|
||||
|
||||
caf->_fileSize = ftell(fd);
|
||||
|
||||
fseek(fd, curPos, SEEK_SET);
|
||||
*/
|
||||
|
||||
caf->_fileSize = lseek(fd, 0, SEEK_END) - caf->_startOffset;
|
||||
NSLog(@"SIZE at %lli", caf->_fileSize);
|
||||
|
||||
NSLog(@"ERROR: %i = %i %i %i", errno, EBADF, ESPIPE, EINVAL);
|
||||
return caf->_fileSize;
|
||||
}
|
||||
|
||||
OSStatus setSizeFunc(void * inRefCon, SInt64 inSize)
|
||||
{
|
||||
NSLog(@"setsize FUNC");
|
||||
|
||||
return -1000; //Not supported at the moment
|
||||
}
|
||||
|
||||
OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, const void *buffer, ByteCount* actualCount)
|
||||
{
|
||||
NSLog(@"WRITE FUNC");
|
||||
return -1000; //Not supported at the moment
|
||||
}
|
||||
#endif
|
||||
|
||||
- (BOOL) open:(const char *)filename
|
||||
{
|
||||
return [self readInfo:filename];
|
||||
}
|
||||
|
||||
- (void) close
|
||||
{
|
||||
OSStatus err;
|
||||
|
||||
#ifdef _USE_WRAPPER_
|
||||
if (_inFd)
|
||||
close(_inFd);
|
||||
AudioFileClose(_audioID);
|
||||
#endif
|
||||
|
||||
err = ExtAudioFileDispose(_in);
|
||||
if(noErr != err) {
|
||||
NSLog(@"Error closing ExtAudioFile");
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL) readInfo:(const char *)filename
|
||||
{
|
||||
OSStatus err;
|
||||
AudioFileTypeID type = 0;
|
||||
NSString *ext;
|
||||
|
||||
#ifdef _USE_WRAPPER_
|
||||
// Open the input file
|
||||
_inFd = open(filename, O_RDONLY, 0777);
|
||||
if (_inFd < 0)
|
||||
{
|
||||
NSLog(@"Error operning file: %s", filename);
|
||||
return NO;
|
||||
}
|
||||
_startOffset = 0;
|
||||
|
||||
ext = [[NSString stringWithCString:filename encoding:NSASCIIStringEncoding] pathExtension];
|
||||
//Find first sync frame for MP3
|
||||
if([ext caseInsensitiveCompare:@"mp3"] == NSOrderedSame) {
|
||||
size_t bytesRead;
|
||||
uint8_t buf[2];
|
||||
|
||||
type = kAudioFileMP3Type;
|
||||
|
||||
for(;;) {
|
||||
bytesRead = read(_inFd, buf, 2);
|
||||
|
||||
|
||||
if(2 != bytesRead) {
|
||||
NSLog(@"Error finding mp3 sync frame");
|
||||
close(_inFd);
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
// found some kind of data
|
||||
if(0x00 != buf[0] || 0x00 != buf[1]) {
|
||||
_startOffset = lseek(_inFd, 0, SEEK_CUR) - 2;
|
||||
NSLog(@"Found sync frame at: %llx", _startOffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if([ext caseInsensitiveCompare:@"aac"] == NSOrderedSame) {
|
||||
type = kAudioFileAAC_ADTSType;
|
||||
}
|
||||
else if([ext caseInsensitiveCompare:@"m4a"] == NSOrderedSame) {
|
||||
type = kAudioFileM4AType;
|
||||
}
|
||||
else if([ext caseInsensitiveCompare:@"mp4"] == NSOrderedSame) {
|
||||
type = kAudioFileMPEG4Type;
|
||||
}
|
||||
|
||||
//Using callbacks with fopen, ftell, fseek, fclose, because the default pread hangs when accessing the same file from multiple threads.
|
||||
err = AudioFileOpenWithCallbacks(self, readFunc, writeFunc, getSizeFunc, setSizeFunc, type, &_audioID);
|
||||
if(noErr != err)
|
||||
{
|
||||
NSLog(@"Error opening with callbacks, falling back: %s", (char *)&err);
|
||||
FSRef ref;
|
||||
close(_inFd);
|
||||
_inFd = 0;
|
||||
|
||||
err = FSPathMakeRef((const UInt8 *)filename, &ref, NULL);
|
||||
if(noErr != err) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
err = AudioFileOpen(&ref, fsRdPerm, type, &_audioID);
|
||||
if(noErr != err) {
|
||||
NSLog(@"Error opening AudioFile: %s", (char *)&err);
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
err = ExtAudioFileWrapAudioFileID(_audioID, NO, &_in);
|
||||
if(noErr != err) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
#else
|
||||
FSRef ref;
|
||||
|
||||
// Open the input file
|
||||
err = FSPathMakeRef((const UInt8 *)filename, &ref, NULL);
|
||||
if(noErr != err) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
err = ExtAudioFileOpen(&ref, &_in);
|
||||
if(noErr != err) {
|
||||
NSLog(@"Error opening file: %s", &err);
|
||||
return NO;
|
||||
}
|
||||
#endif
|
||||
return [self readInfoFromExtAudioFileRef];
|
||||
}
|
||||
|
||||
- (BOOL) readInfoFromExtAudioFileRef
|
||||
{
|
||||
OSStatus err;
|
||||
UInt32 size;
|
||||
SInt64 totalFrames;
|
||||
AudioStreamBasicDescription asbd;
|
||||
|
||||
// Get input file information
|
||||
size = sizeof(asbd);
|
||||
err = ExtAudioFileGetProperty(_in, kExtAudioFileProperty_FileDataFormat, &size, &asbd);
|
||||
if(err != noErr) {
|
||||
err = ExtAudioFileDispose(_in);
|
||||
return NO;
|
||||
}
|
||||
|
||||
size = sizeof(totalFrames);
|
||||
err = ExtAudioFileGetProperty(_in, kExtAudioFileProperty_FileLengthFrames, &size, &totalFrames);
|
||||
if(err != noErr) {
|
||||
err = ExtAudioFileDispose(_in);
|
||||
return NO;
|
||||
}
|
||||
|
||||
#ifdef _USE_WRAPPER_
|
||||
SInt64 totalBytes;
|
||||
|
||||
size = sizeof(totalBytes);
|
||||
err = AudioFileGetProperty(_audioID, kAudioFilePropertyAudioDataByteCount, &size, &totalBytes);
|
||||
if(err != noErr) {
|
||||
[self close];
|
||||
return NO;
|
||||
}
|
||||
NSLog(@"BITRATE: %lli %lli %lf", totalBytes, totalFrames, asbd.mSampleRate);
|
||||
bitrate = round(((totalBytes*8.0)/((double)(totalFrames)/asbd.mSampleRate))/1000.0);
|
||||
#else
|
||||
//Is there a way to get bitrate with extAudioFile?
|
||||
bitrate = 0;
|
||||
#endif
|
||||
|
||||
// Set our properties
|
||||
bitsPerSample = asbd.mBitsPerChannel;
|
||||
channels = asbd.mChannelsPerFrame;
|
||||
frequency = asbd.mSampleRate;
|
||||
|
||||
// mBitsPerChannel will only be set for lpcm formats
|
||||
if(0 == bitsPerSample) {
|
||||
bitsPerSample = 16;
|
||||
}
|
||||
|
||||
totalSize = totalFrames * channels * (bitsPerSample / 8);
|
||||
|
||||
// Set output format
|
||||
AudioStreamBasicDescription result;
|
||||
|
||||
bzero(&result, sizeof(AudioStreamBasicDescription));
|
||||
|
||||
result.mFormatID = kAudioFormatLinearPCM;
|
||||
result.mFormatFlags = kAudioFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsBigEndian;
|
||||
|
||||
result.mSampleRate = frequency;
|
||||
result.mChannelsPerFrame = channels;
|
||||
result.mBitsPerChannel = bitsPerSample;
|
||||
|
||||
result.mBytesPerPacket = channels * (bitsPerSample / 8);
|
||||
result.mFramesPerPacket = 1;
|
||||
result.mBytesPerFrame = channels * (bitsPerSample / 8);
|
||||
|
||||
err = ExtAudioFileSetProperty(_in, kExtAudioFileProperty_ClientDataFormat, sizeof(result), &result);
|
||||
if(noErr != err) {
|
||||
err = ExtAudioFileDispose(_in);
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Further properties
|
||||
isBigEndian = YES;
|
||||
isUnsigned = NO;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (int) fillBuffer:(void *)buf ofSize:(UInt32)size
|
||||
{
|
||||
OSStatus err;
|
||||
AudioBufferList bufferList;
|
||||
UInt32 frameCount;
|
||||
|
||||
// Set up the AudioBufferList
|
||||
bufferList.mNumberBuffers = 1;
|
||||
bufferList.mBuffers[0].mNumberChannels = channels;
|
||||
bufferList.mBuffers[0].mData = buf;
|
||||
bufferList.mBuffers[0].mDataByteSize = size;
|
||||
|
||||
// Read a chunk of PCM input (converted from whatever format)
|
||||
frameCount = (size / (channels * (bitsPerSample / 8)));
|
||||
err = ExtAudioFileRead(_in, &frameCount, &bufferList);
|
||||
if(err != noErr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return frameCount * (channels * (bitsPerSample / 8));
|
||||
}
|
||||
|
||||
- (double) seekToTime:(double)milliseconds
|
||||
{
|
||||
OSStatus err;
|
||||
|
||||
err = ExtAudioFileSeek(_in, ((milliseconds / 1000.f) * frequency));
|
||||
if(noErr != err) {
|
||||
return -1.f;
|
||||
}
|
||||
|
||||
return milliseconds;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,28 +0,0 @@
|
|||
//
|
||||
// FlacFile.h
|
||||
// zyVorbis
|
||||
//
|
||||
// Created by Vincent Spader on 1/25/05.
|
||||
// Copyright 2005 Vincent Spader All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "FLAC/all.h"
|
||||
#import "SoundFile.h"
|
||||
|
||||
#define SAMPLES_PER_WRITE 512
|
||||
#define FLAC__MAX_SUPPORTED_CHANNELS 2
|
||||
#define SAMPLE_BUFFER_SIZE ((FLAC__MAX_BLOCK_SIZE + SAMPLES_PER_WRITE) * FLAC__MAX_SUPPORTED_CHANNELS * (24/8))
|
||||
|
||||
@interface FlacFile : SoundFile {
|
||||
FLAC__FileDecoder *decoder;
|
||||
char buffer[SAMPLE_BUFFER_SIZE];
|
||||
int bufferAmount;
|
||||
}
|
||||
|
||||
- (FLAC__FileDecoder *)decoder;
|
||||
- (char *)buffer;
|
||||
- (int)bufferAmount;
|
||||
- (void)setBufferAmount:(int)amount;
|
||||
|
||||
@end
|
|
@ -1,188 +0,0 @@
|
|||
//
|
||||
// FlacFile.m
|
||||
// zyVorbis
|
||||
//
|
||||
// Created by Vincent Spader on 1/25/05.
|
||||
// Copyright 2005 Vincent Spader All rights reserved.
|
||||
//
|
||||
|
||||
#import "FlacFile.h"
|
||||
|
||||
|
||||
@implementation FlacFile
|
||||
|
||||
FLAC__StreamDecoderWriteStatus WriteProc(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const sampleBuffer[], void *client_data)
|
||||
{
|
||||
// DBLog(@"Write callback");
|
||||
FlacFile *flacFile = (FlacFile *)client_data;
|
||||
unsigned wide_samples = frame->header.blocksize;
|
||||
unsigned channels = frame->header.channels;
|
||||
|
||||
UInt16 *buffer = (UInt16 *)[flacFile buffer];
|
||||
int i, j, c;
|
||||
|
||||
for (i = j = 0; i < wide_samples; i++)
|
||||
{
|
||||
for (c = 0; c < channels; c++, j++)
|
||||
{
|
||||
// buffer[j] = CFSwapInt16LittleToHost(sampleBuffer[c][i]);
|
||||
buffer[j] = sampleBuffer[c][i];
|
||||
}
|
||||
}
|
||||
|
||||
// memcpy([flacFile buffer], sampleBuffer, wide_samples*[flacFile bitsPerSample]/8);
|
||||
[flacFile setBufferAmount:(wide_samples * channels*2)];
|
||||
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
void MetadataProc(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
|
||||
{
|
||||
FlacFile *flacFile = (FlacFile *)client_data;
|
||||
|
||||
flacFile->channels = metadata->data.stream_info.channels;
|
||||
flacFile->frequency = metadata->data.stream_info.sample_rate;
|
||||
flacFile->bitsPerSample = metadata->data.stream_info.bits_per_sample;
|
||||
|
||||
// DBLog(@"METADATAAAA LENGTH: %i %i %f", (int)(metadata->data.stream_info.total_samples),[flacFile frequency], (float)(metadata->data.stream_info.total_samples)/[flacFile frequency]);
|
||||
flacFile->totalSize = metadata->data.stream_info.total_samples*metadata->data.stream_info.channels*metadata->data.stream_info.bits_per_sample/8;
|
||||
}
|
||||
|
||||
void ErrorProc(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
|
||||
{
|
||||
DBLog(@"Error callback");
|
||||
}
|
||||
|
||||
- (BOOL)open:(const char *)filename
|
||||
{
|
||||
FLAC__bool status;
|
||||
|
||||
decoder = FLAC__file_decoder_new();
|
||||
if (decoder == NULL)
|
||||
return NO;
|
||||
|
||||
status = FLAC__file_decoder_set_filename(decoder, filename);
|
||||
if (status == false)
|
||||
return NO;
|
||||
|
||||
status = FLAC__file_decoder_set_write_callback(decoder, WriteProc);
|
||||
if (status == false)
|
||||
return NO;
|
||||
|
||||
status = FLAC__file_decoder_set_metadata_callback(decoder, MetadataProc);
|
||||
if (status == false)
|
||||
return NO;
|
||||
|
||||
status = FLAC__file_decoder_set_error_callback(decoder, ErrorProc);
|
||||
if (status == false)
|
||||
return NO;
|
||||
|
||||
status = FLAC__file_decoder_set_client_data(decoder, self);
|
||||
if (status == false)
|
||||
return NO;
|
||||
|
||||
if (FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK)
|
||||
return NO;
|
||||
|
||||
FLAC__file_decoder_process_until_end_of_metadata(decoder);
|
||||
|
||||
isBigEndian = hostIsBigEndian();
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)readInfo:(const char *)filename
|
||||
{
|
||||
FLAC__StreamMetadata streamInfo;
|
||||
|
||||
FLAC__metadata_get_streaminfo(filename, &streamInfo);
|
||||
|
||||
channels = streamInfo.data.stream_info.channels;
|
||||
frequency = streamInfo.data.stream_info.sample_rate;
|
||||
bitsPerSample = streamInfo.data.stream_info.bits_per_sample;
|
||||
|
||||
totalSize = streamInfo.data.stream_info.total_samples*channels*(bitsPerSample/8);
|
||||
bitrate = 0;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (int)fillBuffer:(void *)buf ofSize:(UInt32)size
|
||||
{
|
||||
int count;
|
||||
int numread;
|
||||
|
||||
if (bufferAmount == 0)
|
||||
{
|
||||
int i;
|
||||
if (FLAC__file_decoder_get_state (decoder) == FLAC__FILE_DECODER_END_OF_FILE)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
i = FLAC__file_decoder_process_single(decoder);// != FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE);
|
||||
//return 0;
|
||||
// [self writeSamplesToBuffer:buffer fromBuffer:sampleBuffer ofSize:(status*2)];
|
||||
// write callback sets bufferAmount...frickin weird, also sets sampleBuffer
|
||||
// bufferAmount = status*4;
|
||||
}
|
||||
|
||||
count = bufferAmount;
|
||||
if (bufferAmount > size)
|
||||
{
|
||||
count = size;
|
||||
}
|
||||
memcpy(buf, buffer, count);
|
||||
|
||||
bufferAmount -= count;
|
||||
|
||||
if (bufferAmount > 0)
|
||||
memmove(buffer, &buffer[count], bufferAmount);
|
||||
|
||||
if (count < size)
|
||||
numread = [self fillBuffer:(&((char *)buf)[count]) ofSize:(size - count)];
|
||||
else
|
||||
numread = 0;
|
||||
|
||||
return count + numread;
|
||||
|
||||
}
|
||||
|
||||
- (void)close
|
||||
{
|
||||
if (decoder)
|
||||
{
|
||||
FLAC__file_decoder_finish(decoder);
|
||||
FLAC__file_decoder_delete(decoder);
|
||||
}
|
||||
decoder = NULL;
|
||||
|
||||
}
|
||||
|
||||
- (double)seekToTime:(double)milliseconds
|
||||
{
|
||||
FLAC__file_decoder_seek_absolute(decoder, frequency * ((double)milliseconds/1000.0));
|
||||
|
||||
return milliseconds;
|
||||
}
|
||||
|
||||
//bs methods
|
||||
- (char *)buffer
|
||||
{
|
||||
return buffer;
|
||||
}
|
||||
- (int)bufferAmount
|
||||
{
|
||||
return bufferAmount;
|
||||
}
|
||||
- (void)setBufferAmount:(int)amount
|
||||
{
|
||||
bufferAmount = amount;
|
||||
}
|
||||
|
||||
- (FLAC__FileDecoder *)decoder
|
||||
{
|
||||
return decoder;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,19 +0,0 @@
|
|||
//
|
||||
// GameFile.h
|
||||
// Cog
|
||||
//
|
||||
// Created by Vincent Spader on 5/29/06.
|
||||
// Copyright 2006 Vincent Spader. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "SoundFile.h"
|
||||
|
||||
#undef HAVE_CONFIG_H
|
||||
|
||||
#import "GME/Music_Emu.h"
|
||||
@interface GameFile : SoundFile {
|
||||
Music_Emu* emu;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,110 +0,0 @@
|
|||
//
|
||||
// GameFile.m
|
||||
// Cog
|
||||
//
|
||||
// Created by Vincent Spader on 5/29/06.
|
||||
// Copyright 2006 Vincent Spader. All rights reserved.
|
||||
//
|
||||
|
||||
#import "GameFile.h"
|
||||
|
||||
#include "GME/Nsf_Emu.h"
|
||||
#include "GME/Gbs_Emu.h"
|
||||
#include "GME/Spc_Emu.h"
|
||||
#include "GME/Vgm_Emu.h"
|
||||
#include "GME/Gym_Emu.h"
|
||||
|
||||
@implementation GameFile
|
||||
|
||||
- (BOOL)open:(const char *)filename
|
||||
{
|
||||
int i;
|
||||
const char* p;
|
||||
char ext[3];
|
||||
|
||||
p = strrchr( (char*) filename, '.' )+1;
|
||||
NSLog(@"OPENING GAME FILE: %s", filename);
|
||||
NSLog(@"Extension: %s", p);
|
||||
|
||||
if (!p || strlen(p) != 3)
|
||||
return NO;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
ext[i] = toupper(p[i]);
|
||||
ext[3] = 0;
|
||||
|
||||
if (!ext)
|
||||
emu = NULL;
|
||||
else if ( !strcmp( ext, "NSF" ) )
|
||||
emu = new Nsf_Emu;
|
||||
else if ( !strcmp( ext, "GBS" ) )
|
||||
emu = new Gbs_Emu;
|
||||
else if ( !strcmp( ext, "SPC" ) )
|
||||
emu = new Spc_Emu;
|
||||
else if ( !strcmp( ext, "VGM" ) || !strcmp( ext, "VGZ" ) )
|
||||
emu = new Vgm_Emu;
|
||||
else if ( !strcmp( ext, "GYM" ) )
|
||||
emu = new Gym_Emu;
|
||||
else
|
||||
emu = NULL;
|
||||
|
||||
NSLog(@"EMU IS: %i", emu);
|
||||
if (!emu)
|
||||
return NO;
|
||||
|
||||
emu->set_sample_rate(44100);
|
||||
emu->load_file(filename);
|
||||
emu->start_track( 0 );
|
||||
frequency = 44100;
|
||||
channels = 2;
|
||||
|
||||
bitsPerSample = 8 * sizeof(Music_Emu::sample_t);
|
||||
|
||||
totalSize = emu->track_count() * frequency*(bitsPerSample/8)*channels;
|
||||
|
||||
isBigEndian = YES;
|
||||
|
||||
NSLog(@"OPENED GAME FILE:");
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)readInfo:(const char *)filename
|
||||
{
|
||||
return [self open:filename];
|
||||
}
|
||||
|
||||
- (int)fillBuffer:(void *)buf ofSize:(UInt32)size
|
||||
{
|
||||
int numSamples = size / ((bitsPerSample/8));
|
||||
|
||||
emu->play(numSamples, (short int *)buf);
|
||||
|
||||
return size; //No such thing as EOF
|
||||
}
|
||||
|
||||
//Cheap hack until I figure out how to actually support multiple tracks in a single file.
|
||||
- (double)seekToTime:(double)milliseconds
|
||||
{
|
||||
int track;
|
||||
track = (int)(milliseconds/1000.0);
|
||||
NSLog(@"Track: %i", track);
|
||||
if (track > emu->track_count())
|
||||
{
|
||||
track = emu->track_count();
|
||||
}
|
||||
emu->start_track( track );
|
||||
|
||||
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
- (void)close
|
||||
{
|
||||
if (emu)
|
||||
delete emu;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@end
|
|
@ -1,39 +0,0 @@
|
|||
//
|
||||
// MADFile.h
|
||||
// Cog
|
||||
//
|
||||
// Created by Vincent Spader on 6/17/06.
|
||||
// Copyright 2006 Vincent Spader. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "SoundFile.h"
|
||||
#undef HAVE_CONFIG_H
|
||||
#import "MAD/mad.h"
|
||||
|
||||
#define INPUT_BUFFER_SIZE 5*8192
|
||||
|
||||
|
||||
@interface MADFile : SoundFile {
|
||||
struct mad_stream _stream;
|
||||
struct mad_frame _frame;
|
||||
struct mad_synth _synth;
|
||||
mad_timer_t _timer;
|
||||
mad_timer_t _duration;
|
||||
unsigned char _inputBuffer[INPUT_BUFFER_SIZE+MAD_BUFFER_GUARD];
|
||||
unsigned char *_outputBuffer;
|
||||
int _outputAvailable;
|
||||
int _fileSize;
|
||||
|
||||
FILE *_inFd;
|
||||
|
||||
BOOL _seekSkip;
|
||||
|
||||
//For gapless playback of mp3s
|
||||
BOOL _gapless;
|
||||
long _currentFrame;
|
||||
int _startPadding;
|
||||
int _endPadding;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,570 +0,0 @@
|
|||
//
|
||||
// MADFile.m
|
||||
// Cog
|
||||
//
|
||||
// Created by Vincent Spader on 6/17/06.
|
||||
// Copyright 2006 Vincent Spader. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MADFile.h"
|
||||
#undef HAVE_CONFIG_H
|
||||
#import <ID3Tag/id3tag.h>
|
||||
|
||||
@implementation MADFile
|
||||
|
||||
/*XING FUN*/
|
||||
|
||||
#define XING_MAGIC (('X' << 24) | ('i' << 16) | ('n' << 8) | 'g')
|
||||
#define INFO_MAGIC (('I' << 24) | ('n' << 16) | ('f' << 8) | 'o')
|
||||
#define LAME_MAGIC (('L' << 24) | ('A' << 16) | ('M' << 8) | 'E')
|
||||
|
||||
struct xing
|
||||
{
|
||||
long flags; /* valid fields (see below) */
|
||||
unsigned long frames; /* total number of frames */
|
||||
unsigned long bytes; /* total number of bytes */
|
||||
unsigned char toc[100]; /* 100-point seek table */
|
||||
long scale; /* ?? */
|
||||
};
|
||||
|
||||
struct lame
|
||||
{
|
||||
long flags;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
XING_FRAMES = 0x00000001L,
|
||||
XING_BYTES = 0x00000002L,
|
||||
XING_TOC = 0x00000004L,
|
||||
XING_SCALE = 0x00000008L
|
||||
};
|
||||
|
||||
int lame_parse(struct lame *lame, struct mad_bitptr *ptr, unsigned int bitlen)
|
||||
{
|
||||
unsigned long magic;
|
||||
unsigned long garbage;
|
||||
|
||||
magic = mad_bit_read(ptr, 32); //4 bytes
|
||||
|
||||
if (magic != LAME_MAGIC)
|
||||
return 0;
|
||||
|
||||
mad_bit_skip(ptr, 17*8); //17 bytes skipped
|
||||
garbage = mad_bit_read(ptr, 24); //3 bytes
|
||||
// _startPadding = (garbage >> 12) & 0x000FFF;
|
||||
// _endPadding = garbage & 0x000FFF;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int xing_parse(struct xing *xing, struct mad_bitptr *ptr, unsigned int bitlen)
|
||||
{
|
||||
xing->flags = 0;
|
||||
unsigned long magic;
|
||||
|
||||
if (bitlen < 64)
|
||||
return 0;
|
||||
|
||||
magic = mad_bit_read(ptr, 32);
|
||||
if (magic != INFO_MAGIC && magic != XING_MAGIC)
|
||||
return 0;
|
||||
|
||||
xing->flags = mad_bit_read(ptr, 32);
|
||||
bitlen -= 64;
|
||||
|
||||
if (xing->flags & XING_FRAMES) {
|
||||
if (bitlen < 32)
|
||||
return 0;
|
||||
|
||||
xing->frames = mad_bit_read(ptr, 32);
|
||||
bitlen -= 32;
|
||||
}
|
||||
|
||||
if (xing->flags & XING_BYTES) {
|
||||
if (bitlen < 32)
|
||||
return 0;
|
||||
|
||||
xing->bytes = mad_bit_read(ptr, 32);
|
||||
bitlen -= 32;
|
||||
}
|
||||
|
||||
if (xing->flags & XING_TOC) {
|
||||
int i;
|
||||
|
||||
if (bitlen < 800)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < 100; ++i)
|
||||
xing->toc[i] = mad_bit_read(ptr, 8);
|
||||
|
||||
bitlen -= 800;
|
||||
}
|
||||
|
||||
if (xing->flags & XING_SCALE) {
|
||||
if (bitlen < 32)
|
||||
return 0;
|
||||
|
||||
xing->scale = mad_bit_read(ptr, 32);
|
||||
bitlen -= 32;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int parse_headers(struct xing *xing, struct lame *lame, struct mad_bitptr ptr, unsigned int bitlen)
|
||||
{
|
||||
xing->flags = 0;
|
||||
lame->flags = 0;
|
||||
|
||||
if (xing_parse(xing, &ptr, bitlen))
|
||||
{
|
||||
lame_parse(lame, &ptr, bitlen);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)scanFileFast:(BOOL)fast useXing:(BOOL)use_xing
|
||||
{
|
||||
const int BUFFER_SIZE = 16*1024;
|
||||
const int N_AVERAGE_FRAMES = 10;
|
||||
|
||||
struct mad_stream stream;
|
||||
struct mad_header header;
|
||||
struct mad_frame frame; /* to read xing data */
|
||||
struct xing xing;
|
||||
struct lame lame;
|
||||
int remainder = 0;
|
||||
int data_used = 0;
|
||||
int len = 0;
|
||||
int tagsize = 0;
|
||||
int frames = 0;
|
||||
unsigned char buffer[BUFFER_SIZE];
|
||||
BOOL has_xing = NO;
|
||||
BOOL vbr = NO;
|
||||
|
||||
mad_stream_init (&stream);
|
||||
mad_header_init (&header);
|
||||
mad_frame_init (&frame);
|
||||
|
||||
bitrate = 0;
|
||||
_duration = mad_timer_zero;
|
||||
|
||||
frames = 0;
|
||||
|
||||
fseek(_inFd, 0, SEEK_END);
|
||||
_fileSize = ftell(_inFd);
|
||||
fseek(_inFd, 0, SEEK_SET);
|
||||
|
||||
BOOL done = NO;
|
||||
|
||||
while (!done)
|
||||
{
|
||||
remainder = stream.bufend - stream.next_frame;
|
||||
|
||||
memcpy (buffer, stream.this_frame, remainder);
|
||||
len = fread(buffer + remainder, 1, BUFFER_SIZE - remainder, _inFd);
|
||||
|
||||
if (len <= 0)
|
||||
break;
|
||||
|
||||
mad_stream_buffer (&stream, buffer, len + remainder);
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (mad_header_decode (&header, &stream) == -1)
|
||||
{
|
||||
if (stream.error == MAD_ERROR_BUFLEN)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (!MAD_RECOVERABLE (stream.error))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (stream.error == MAD_ERROR_LOSTSYNC)
|
||||
{
|
||||
/* ignore LOSTSYNC due to ID3 tags */
|
||||
tagsize = id3_tag_query (stream.this_frame,
|
||||
stream.bufend -
|
||||
stream.this_frame);
|
||||
if (tagsize > 0)
|
||||
{
|
||||
mad_stream_skip (&stream, tagsize);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
frames++;
|
||||
|
||||
mad_timer_add (&_duration, header.duration);
|
||||
data_used += stream.next_frame - stream.this_frame;
|
||||
if (frames == 1)
|
||||
{
|
||||
/* most of these *should* remain constant */
|
||||
bitrate = header.bitrate;
|
||||
frequency = header.samplerate;
|
||||
channels = MAD_NCHANNELS(&header);
|
||||
|
||||
if (use_xing)
|
||||
{
|
||||
frame.header = header;
|
||||
if (mad_frame_decode(&frame, &stream) == -1)
|
||||
continue;
|
||||
|
||||
if (parse_headers(&xing, &lame, stream.anc_ptr, stream.anc_bitlen))
|
||||
{
|
||||
has_xing = YES;
|
||||
vbr = YES;
|
||||
|
||||
frames = xing.frames;
|
||||
mad_timer_multiply (&_duration, frames);
|
||||
|
||||
bitrate = 8.0 * xing.bytes / mad_timer_count(_duration, MAD_UNITS_SECONDS);
|
||||
done = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* perhaps we have a VBR file */
|
||||
if (bitrate != header.bitrate)
|
||||
vbr = YES;
|
||||
if (vbr)
|
||||
bitrate += header.bitrate;
|
||||
}
|
||||
|
||||
if ((!vbr || (vbr && !has_xing)) && fast && frames >= N_AVERAGE_FRAMES)
|
||||
{
|
||||
float frame_size = ((double)data_used) / N_AVERAGE_FRAMES;
|
||||
frames = (_fileSize - tagsize) / frame_size;
|
||||
|
||||
_duration.seconds /= N_AVERAGE_FRAMES;
|
||||
_duration.fraction /= N_AVERAGE_FRAMES;
|
||||
mad_timer_multiply (&_duration, frames);
|
||||
|
||||
done = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (stream.error != MAD_ERROR_BUFLEN)
|
||||
break;
|
||||
}
|
||||
|
||||
if (vbr && !has_xing)
|
||||
bitrate = bitrate / frames;
|
||||
|
||||
mad_frame_finish (&frame);
|
||||
mad_header_finish (&header);
|
||||
mad_stream_finish (&stream);
|
||||
|
||||
totalSize = (mad_timer_count(_duration, MAD_UNITS_MILLISECONDS)*(frequency/1000.0))*channels*(bitsPerSample/8);
|
||||
|
||||
bitrate /= 1000;
|
||||
NSLog(@"BITRATE: %i %i", bitrate, vbr);
|
||||
fseek(_inFd, 0, SEEK_SET);
|
||||
|
||||
return frames != 0;
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)open:(const char *)filename
|
||||
{
|
||||
/* First the structures used by libmad must be initialized. */
|
||||
mad_stream_init(&_stream);
|
||||
mad_frame_init(&_frame);
|
||||
mad_synth_init(&_synth);
|
||||
mad_timer_reset(&_timer);
|
||||
|
||||
_inFd = fopen(filename, "r");
|
||||
if (!_inFd)
|
||||
return NO;
|
||||
|
||||
bitsPerSample = 16;
|
||||
isBigEndian=YES;
|
||||
isUnsigned=NO;
|
||||
|
||||
return [self scanFileFast:YES useXing:YES];
|
||||
}
|
||||
|
||||
- (BOOL)readInfo:(const char *)filename
|
||||
{
|
||||
return [self open:filename];
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale PCM data
|
||||
*/
|
||||
static inline signed int scale (mad_fixed_t sample)
|
||||
{
|
||||
BOOL hard_limit = YES;
|
||||
// BOOL replaygain = NO;
|
||||
/* replayGain by SamKR */
|
||||
double scale = -1;
|
||||
/* if (replaygain)
|
||||
{
|
||||
if (file_info->has_replaygain)
|
||||
{
|
||||
scale = file_info->replaygain_track_scale;
|
||||
if (file_info->replaygain_album_scale != -1
|
||||
&& (scale==-1 || ! xmmsmad_config.replaygain.track_mode))
|
||||
{
|
||||
scale = file_info->replaygain_album_scale;
|
||||
}
|
||||
}
|
||||
if (scale == -1)
|
||||
scale = xmmsmad_config.replaygain.default_scale;
|
||||
}
|
||||
*/
|
||||
if (scale == -1)
|
||||
scale = 1.0;
|
||||
|
||||
/* hard-limit (clipping-prevention) */
|
||||
if (hard_limit)
|
||||
{
|
||||
/* convert to double before computation, to avoid mad_fixed_t wrapping */
|
||||
double x = mad_f_todouble(sample) * scale;
|
||||
static const double k = 0.5; // -6dBFS
|
||||
if (x > k)
|
||||
{
|
||||
x = tanh((x - k) / (1-k)) * (1-k) + k;
|
||||
}
|
||||
else if(x < -k)
|
||||
{
|
||||
x = tanh((x + k) / (1-k)) * (1-k) - k;
|
||||
}
|
||||
sample = x * (MAD_F_ONE);
|
||||
}
|
||||
else
|
||||
sample *= scale;
|
||||
|
||||
int n_bits_to_loose = MAD_F_FRACBITS + 1 - 16;
|
||||
|
||||
/* round */
|
||||
/* add half of the bits_to_loose range to round */
|
||||
sample += (1L << (n_bits_to_loose - 1));
|
||||
|
||||
/* clip */
|
||||
/* make sure we are between -1 and 1 */
|
||||
if (sample >= MAD_F_ONE)
|
||||
{
|
||||
sample = MAD_F_ONE - 1;
|
||||
}
|
||||
else if (sample < -MAD_F_ONE)
|
||||
{
|
||||
sample = -MAD_F_ONE;
|
||||
}
|
||||
|
||||
/* quantize */
|
||||
/*
|
||||
* Turn our mad_fixed_t into an integer.
|
||||
* Shift all but 16-bits of the fractional part
|
||||
* off the right hand side and shift an extra place
|
||||
* to get the sign bit.
|
||||
*/
|
||||
sample >>= n_bits_to_loose;
|
||||
|
||||
return sample;
|
||||
}
|
||||
|
||||
|
||||
- (void)writeOutput
|
||||
{
|
||||
unsigned int nsamples;
|
||||
mad_fixed_t const *left_ch, *right_ch;
|
||||
|
||||
// if (_outputAvailable) {
|
||||
// NSLog(@"Losing Output: %i", _outputAvailable);
|
||||
// }
|
||||
nsamples = _synth.pcm.length;
|
||||
left_ch = _synth.pcm.samples[0];
|
||||
right_ch = _synth.pcm.samples[1];
|
||||
_outputAvailable = nsamples * channels * (bitsPerSample/8);
|
||||
|
||||
if (_outputBuffer)
|
||||
free(_outputBuffer);
|
||||
|
||||
_outputBuffer = (unsigned char *) malloc (_outputAvailable * sizeof (char));
|
||||
|
||||
unsigned char *outputPtr = _outputBuffer;
|
||||
|
||||
int i;
|
||||
for (i=0; i < nsamples; i++)
|
||||
{
|
||||
signed short sample;
|
||||
/* output sample(s) in 16-bit signed little-endian PCM */
|
||||
sample = scale(left_ch[i]);
|
||||
*(outputPtr++) = sample>>8;
|
||||
*(outputPtr++) = sample & 0xff;
|
||||
|
||||
if (channels == 2)
|
||||
{
|
||||
sample = scale(right_ch[i]);
|
||||
*(outputPtr++) = sample>>8;
|
||||
*(outputPtr++) = sample & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (int)fillBuffer:(void *)buf ofSize:(UInt32)size
|
||||
{
|
||||
int remainder;
|
||||
int len;
|
||||
BOOL eof = NO;
|
||||
int amountToCopy = size;
|
||||
int amountRemaining = size;
|
||||
|
||||
if (amountToCopy > _outputAvailable)
|
||||
amountToCopy = _outputAvailable;
|
||||
|
||||
if (amountToCopy) {
|
||||
memcpy(buf, _outputBuffer, amountToCopy);
|
||||
memmove(_outputBuffer, _outputBuffer + amountToCopy, _outputAvailable - amountToCopy);
|
||||
|
||||
amountRemaining -= amountToCopy;
|
||||
_outputAvailable -= amountToCopy;
|
||||
}
|
||||
|
||||
while (amountRemaining > 0 && !eof) {
|
||||
if (_stream.buffer == NULL || _stream.error == MAD_ERROR_BUFLEN)
|
||||
{
|
||||
if (!_seekSkip)
|
||||
{
|
||||
remainder = _stream.bufend - _stream.next_frame;
|
||||
if (remainder)
|
||||
memmove(_inputBuffer, _stream.this_frame, remainder);
|
||||
}
|
||||
else
|
||||
{
|
||||
remainder = 0;
|
||||
}
|
||||
|
||||
len = fread(_inputBuffer+remainder, 1, INPUT_BUFFER_SIZE-remainder, _inFd);
|
||||
if (len <= 0)
|
||||
{
|
||||
eof = YES;
|
||||
break;
|
||||
}
|
||||
|
||||
len += remainder;
|
||||
if (len < MAD_BUFFER_GUARD) {
|
||||
int i;
|
||||
for (i = len; i < MAD_BUFFER_GUARD; i++)
|
||||
_inputBuffer[i] = 0;
|
||||
len = MAD_BUFFER_GUARD;
|
||||
}
|
||||
|
||||
mad_stream_buffer(&_stream, _inputBuffer, len);
|
||||
_stream.error = 0;
|
||||
|
||||
if (_seekSkip)
|
||||
{
|
||||
int skip = 2;
|
||||
do
|
||||
{
|
||||
if (mad_frame_decode (&_frame, &_stream) == 0)
|
||||
{
|
||||
mad_timer_add (&_timer, _frame.header.duration);
|
||||
if (--skip == 0)
|
||||
mad_synth_frame (&_synth, &_frame);
|
||||
}
|
||||
else if (!MAD_RECOVERABLE (_stream.error))
|
||||
break;
|
||||
} while (skip);
|
||||
|
||||
_seekSkip = NO;
|
||||
}
|
||||
|
||||
}
|
||||
if (mad_frame_decode(&_frame, &_stream) == -1) {
|
||||
if (!MAD_RECOVERABLE (_stream.error))
|
||||
{
|
||||
if(_stream.error==MAD_ERROR_BUFLEN) {
|
||||
continue;
|
||||
}
|
||||
|
||||
eof = YES;
|
||||
}
|
||||
|
||||
if (_stream.error == MAD_ERROR_LOSTSYNC)
|
||||
{
|
||||
// ignore LOSTSYNC due to ID3 tags
|
||||
int tagsize = id3_tag_query (_stream.this_frame,
|
||||
_stream.bufend -
|
||||
_stream.this_frame);
|
||||
if (tagsize > 0)
|
||||
{
|
||||
mad_stream_skip (&_stream, tagsize);
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
mad_timer_add (&_timer, _frame.header.duration);
|
||||
|
||||
mad_synth_frame (&_synth, &_frame);
|
||||
|
||||
[self writeOutput];
|
||||
amountToCopy = amountRemaining;
|
||||
if (amountToCopy > _outputAvailable) {
|
||||
amountToCopy = _outputAvailable;
|
||||
}
|
||||
if (amountRemaining < amountToCopy) {
|
||||
amountToCopy = amountRemaining;
|
||||
}
|
||||
|
||||
memcpy(((char *)buf)+(size-amountRemaining), _outputBuffer, amountToCopy);
|
||||
memmove(_outputBuffer, _outputBuffer + amountToCopy, _outputAvailable - amountToCopy);
|
||||
amountRemaining -= amountToCopy;
|
||||
_outputAvailable -= amountToCopy;
|
||||
}
|
||||
|
||||
return (size - amountRemaining);
|
||||
}
|
||||
|
||||
- (void)close
|
||||
{
|
||||
fclose(_inFd);
|
||||
|
||||
mad_synth_finish(&_synth);
|
||||
mad_frame_finish(&_frame);
|
||||
mad_stream_finish(&_stream);
|
||||
}
|
||||
|
||||
- (double)seekToTime:(double)milliseconds
|
||||
{
|
||||
int new_position;
|
||||
int seconds = milliseconds/1000.0;
|
||||
int total_seconds = mad_timer_count(_duration, MAD_UNITS_SECONDS);
|
||||
|
||||
if (seconds > total_seconds)
|
||||
seconds = total_seconds;
|
||||
|
||||
mad_timer_set(&_timer, seconds, 0, 0);
|
||||
new_position = ((double) seconds / (double) total_seconds) * _fileSize;
|
||||
|
||||
fseek(_inFd, new_position, SEEK_SET);
|
||||
mad_stream_sync(&_stream);
|
||||
_stream.error = MAD_ERROR_BUFLEN;
|
||||
_stream.sync = 0;
|
||||
_outputAvailable = 0;
|
||||
|
||||
mad_frame_mute(&_frame);
|
||||
mad_synth_mute(&_synth);
|
||||
|
||||
_seekSkip = YES;
|
||||
|
||||
return seconds*1000.0;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
//
|
||||
// MonkeysFile.h
|
||||
// zyVorbis
|
||||
//
|
||||
// Created by Vincent Spader on 1/30/05.
|
||||
// Copyright 2005 Vincent Spader All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <MAC/All.h>
|
||||
#import <MAC/MACLib.h>
|
||||
|
||||
#import "SoundFile.h"
|
||||
|
||||
@interface MonkeysFile : SoundFile {
|
||||
IAPEDecompress * decompress;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,83 +0,0 @@
|
|||
//
|
||||
// MonkeysFile.m
|
||||
// zyVorbis
|
||||
//
|
||||
// Created by Vincent Spader on 1/30/05.
|
||||
// Copyright 2005 Vincent Spader All rights reserved.
|
||||
//
|
||||
|
||||
#import "MonkeysFile.h"
|
||||
#import "MAC/ApeInfo.h"
|
||||
#import "MAC/CharacterHelper.h"
|
||||
|
||||
@implementation MonkeysFile
|
||||
|
||||
- (BOOL)open:(const char *)filename
|
||||
{
|
||||
int n;
|
||||
str_utf16 *chars = NULL;
|
||||
|
||||
chars = GetUTF16FromUTF8((const unsigned char *)filename);
|
||||
if(chars == NULL)
|
||||
return NO;
|
||||
|
||||
decompress = CreateIAPEDecompress(chars, &n);
|
||||
free(chars);
|
||||
|
||||
if (decompress == NULL)
|
||||
{
|
||||
DBLog(@"ERROR OPENING FILE");
|
||||
return NO;
|
||||
}
|
||||
|
||||
frequency = decompress->GetInfo(APE_INFO_SAMPLE_RATE);
|
||||
bitsPerSample = decompress->GetInfo(APE_INFO_BITS_PER_SAMPLE);
|
||||
channels = decompress->GetInfo(APE_INFO_CHANNELS);
|
||||
|
||||
totalSize = decompress->GetInfo(APE_INFO_TOTAL_BLOCKS)*bitsPerSample/8*channels;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)readInfo:(const char *)filename
|
||||
{
|
||||
return [self open:filename];
|
||||
}
|
||||
|
||||
- (int)fillBuffer:(void *)buf ofSize:(UInt32)size
|
||||
{
|
||||
int n;
|
||||
int numread;
|
||||
int blockAlign = decompress->GetInfo(APE_INFO_BLOCK_ALIGN);
|
||||
n = decompress->GetData((char *)buf, size/blockAlign, &numread);
|
||||
if (n != ERROR_SUCCESS)
|
||||
{
|
||||
DBLog(@"ERROR: %i", n);
|
||||
return 0;
|
||||
}
|
||||
numread *= blockAlign;
|
||||
// DBLog(@"READ DATA: %i", numread);
|
||||
|
||||
// DBLog(@"NUMREAD: %i", numread);
|
||||
return numread;
|
||||
}
|
||||
|
||||
- (void)close
|
||||
{
|
||||
// DBLog(@"CLOSE");
|
||||
if (decompress)
|
||||
delete decompress;
|
||||
|
||||
decompress = NULL;
|
||||
}
|
||||
|
||||
- (double)seekToTime:(double)milliseconds
|
||||
{
|
||||
int r;
|
||||
// DBLog(@"HELLO: %i", int(frequency*((double)milliseconds/1000.0)));
|
||||
r = decompress->Seek(int(frequency*((double)milliseconds/1000.0)));
|
||||
|
||||
return milliseconds;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,30 +0,0 @@
|
|||
//
|
||||
// MusepackFile.h
|
||||
// zyVorbis
|
||||
//
|
||||
// Created by Vincent Spader on 1/23/05.
|
||||
// Copyright 2005 Vincent Spader All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <MPCDec/mpcdec.h>
|
||||
#import "SoundFile.h"
|
||||
|
||||
|
||||
@interface MusepackFile : SoundFile {
|
||||
FILE *inFd;
|
||||
mpc_decoder decoder;
|
||||
mpc_reader_file reader;
|
||||
mpc_streaminfo info;
|
||||
|
||||
// int undecodedSize;
|
||||
|
||||
char buffer[MPC_FRAME_LENGTH*4];
|
||||
int bufferAmount;
|
||||
}
|
||||
- (BOOL)writeSamplesToBuffer:(uint16_t *)sample_buffer fromBuffer:(const MPC_SAMPLE_FORMAT *)p_buffer ofSize:(unsigned)p_size;
|
||||
|
||||
//- (FILE *)inFd;
|
||||
//- (int)undecodedSize;
|
||||
|
||||
@end
|
|
@ -1,213 +0,0 @@
|
|||
//
|
||||
// MusepackFile.m
|
||||
// zyVorbis
|
||||
//
|
||||
// Created by Vincent Spader on 1/23/05.
|
||||
// Copyright 2005 Vincent Spader All rights reserved.
|
||||
//
|
||||
|
||||
#import "MusepackFile.h"
|
||||
|
||||
@implementation MusepackFile
|
||||
|
||||
//callbacks
|
||||
/*
|
||||
mpc_int32_t ReadProc(void *data, void *ptr, mpc_int32_t size)
|
||||
{
|
||||
DBLog(@"Reading: %i", size);
|
||||
MusepackFile *f = (MusepackFile *) data;
|
||||
|
||||
return fread(ptr, 1, size, [f inFd]);
|
||||
}
|
||||
|
||||
BOOL SeekProc(void *data, mpc_int32_t offset)
|
||||
{
|
||||
MusepackFile *f = (MusepackFile *) data;
|
||||
// DBLog(@"Seeking: %i %i", offset, f->reader.is_seekable);
|
||||
|
||||
return !fseek([f inFd], offset, SEEK_SET);
|
||||
}
|
||||
|
||||
mpc_int32_t TellProc(void *data)
|
||||
{
|
||||
DBLog(@"Tell");
|
||||
MusepackFile *f = (MusepackFile *) data;
|
||||
return ftell([f inFd]);
|
||||
}
|
||||
|
||||
mpc_int32_t GetSizeProc(void *data)
|
||||
{
|
||||
DBLog(@"Size");
|
||||
|
||||
MusepackFile *f = (MusepackFile *) data;
|
||||
return [f undecodedSize];
|
||||
}
|
||||
|
||||
BOOL CanSeekProc(void *data)
|
||||
{
|
||||
DBLog(@"Can seek");
|
||||
|
||||
MusepackFile *f = (MusepackFile *) data;
|
||||
return YES;
|
||||
}
|
||||
*/
|
||||
//real ish
|
||||
- (BOOL)open:(const char *)filename
|
||||
{
|
||||
if ([self readInfo:filename] == NO)
|
||||
return NO;
|
||||
|
||||
/* instantiate a decoder with our file reader */
|
||||
mpc_decoder_setup(&decoder, &reader);
|
||||
if (!mpc_decoder_initialize(&decoder, &info))
|
||||
{
|
||||
DBLog(@"Error initializing decoder.");
|
||||
return NO;
|
||||
}
|
||||
// DBLog(@"Ok to go...");
|
||||
|
||||
isBigEndian = hostIsBigEndian();
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)readInfo:(const char *)filename
|
||||
{
|
||||
inFd = fopen(filename, "rb");
|
||||
if (inFd == 0)
|
||||
return NO;
|
||||
|
||||
mpc_reader_setup_file_reader(&reader , inFd);
|
||||
|
||||
mpc_streaminfo_init(&info);
|
||||
if (mpc_streaminfo_read(&info, &reader) != ERROR_CODE_OK)
|
||||
{
|
||||
DBLog(@"Not a valid musepack file.");
|
||||
return NO;
|
||||
}
|
||||
|
||||
bitrate = (int)(info.average_bitrate/1000.0);
|
||||
frequency = info.sample_freq;
|
||||
bitsPerSample = 16;
|
||||
channels = 2;
|
||||
|
||||
totalSize = mpc_streaminfo_get_length_samples(&info)*channels*bitsPerSample/8;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)writeSamplesToBuffer:(uint16_t *)sample_buffer fromBuffer:(const MPC_SAMPLE_FORMAT *)p_buffer ofSize:(unsigned)p_size
|
||||
{
|
||||
unsigned n;
|
||||
int m_bps = 16;
|
||||
int clip_min = - 1 << (m_bps - 1),
|
||||
clip_max = (1 << (m_bps - 1)) - 1,
|
||||
float_scale = 1 << (m_bps - 1);
|
||||
|
||||
for (n = 0; n < p_size; n++)
|
||||
{
|
||||
int val;
|
||||
#ifdef MPC_FIXED_POINT
|
||||
val = shift_signed( p_buffer[n], m_bps - MPC_FIXED_POINT_SCALE_SHIFT );
|
||||
#else
|
||||
val = (int)( p_buffer[n] * float_scale );
|
||||
#endif
|
||||
|
||||
if (val < clip_min)
|
||||
val = clip_min;
|
||||
else if (val > clip_max)
|
||||
val = clip_max;
|
||||
|
||||
// sample_buffer[n] = CFSwapInt16LittleToHost(val);
|
||||
sample_buffer[n] = val;
|
||||
}
|
||||
|
||||
// DBLog(@"Samples written.");
|
||||
// m_data_bytes_written += p_size * (m_bps >> 3);
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (int)fillBuffer:(void *)buf ofSize:(UInt32)size
|
||||
{
|
||||
int numread = bufferAmount;
|
||||
int count = 0;
|
||||
MPC_SAMPLE_FORMAT sampleBuffer[MPC_DECODER_BUFFER_LENGTH];
|
||||
// DBLog(@"Fill buffer: %i", size);
|
||||
//Fill from buffer, going by bufferAmount
|
||||
//if still needs more, decode and repeat
|
||||
if (bufferAmount == 0)
|
||||
{
|
||||
/* returns the length of the samples*/
|
||||
|
||||
unsigned status = mpc_decoder_decode(&decoder, sampleBuffer, 0, 0);
|
||||
if (status == (unsigned)( -1))
|
||||
{
|
||||
//decode error
|
||||
DBLog(@"Decode error");
|
||||
return 0;
|
||||
}
|
||||
else if (status == 0) //EOF
|
||||
{
|
||||
// DBLog(@"AHHHHHH EOF");
|
||||
return 0;
|
||||
}
|
||||
else //status>0 /* status == MPC_FRAME_LENGTH */
|
||||
{
|
||||
[self writeSamplesToBuffer:((uint16_t*)buffer) fromBuffer:sampleBuffer ofSize:(status*2)];
|
||||
}
|
||||
|
||||
bufferAmount = status*4;
|
||||
}
|
||||
|
||||
count = bufferAmount;
|
||||
if (bufferAmount > size)
|
||||
{
|
||||
count = size;
|
||||
}
|
||||
|
||||
memcpy(buf, buffer, count);
|
||||
|
||||
bufferAmount -= count;
|
||||
|
||||
if (bufferAmount > 0)
|
||||
memmove(buffer, &buffer[count], bufferAmount);
|
||||
|
||||
if (count < size)
|
||||
numread = [self fillBuffer:(&((char *)buf)[count]) ofSize:(size - count)];
|
||||
else
|
||||
numread = 0;
|
||||
|
||||
return count + numread;
|
||||
}
|
||||
|
||||
- (void)close
|
||||
{
|
||||
fclose(inFd);
|
||||
}
|
||||
|
||||
- (double)seekToTime:(double)milliseconds
|
||||
{
|
||||
BOOL r;
|
||||
// double n = milliseconds;
|
||||
// DBLog(@"Milliseconds: %f", n);
|
||||
// DBLog(@"SEEKING TO: %f", (double)milliseconds/1000.0);
|
||||
|
||||
r = mpc_decoder_seek_sample(&decoder, frequency*((double)milliseconds/1000.0));
|
||||
// DBLog(@"SEEK RESULT: %i", r);
|
||||
|
||||
return milliseconds;
|
||||
}
|
||||
|
||||
//accessors
|
||||
/*
|
||||
- (FILE *)inFd
|
||||
{
|
||||
return inFd;
|
||||
}
|
||||
|
||||
- (int)undecodedSize
|
||||
{
|
||||
return undecodedSize;
|
||||
}
|
||||
*/
|
||||
@end
|
|
@ -1,24 +0,0 @@
|
|||
//
|
||||
// ShnFile.h
|
||||
// Cog
|
||||
//
|
||||
// Created by Vincent Spader on 6/6/05.
|
||||
// Copyright 2005 Vincent Spader All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <Shorten/shn_reader.h>
|
||||
|
||||
#import "SoundFile.h"
|
||||
|
||||
@interface ShnFile : SoundFile {
|
||||
//shn_file *handle;
|
||||
shn_reader *decoder;
|
||||
|
||||
long bufferSize; //total size
|
||||
void *buffer;
|
||||
void *inputBuffer;//derek
|
||||
long bufferAmount; //amount currently in
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,158 +0,0 @@
|
|||
//
|
||||
// ShnFile.mm
|
||||
// Cog
|
||||
//
|
||||
// Created by Vincent Spader on 6/6/05.
|
||||
// Copyright 2005 Vincent Spader All rights reserved.
|
||||
//
|
||||
|
||||
#import "ShnFile.h"
|
||||
|
||||
@implementation ShnFile
|
||||
|
||||
- (BOOL)open:(const char *)filename
|
||||
{
|
||||
if ([self readInfo:filename] == NO)
|
||||
return NO;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)readInfo:(const char *)filename
|
||||
{
|
||||
decoder = new shn_reader;
|
||||
|
||||
if (!decoder)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
decoder->open(filename, true);
|
||||
|
||||
bufferSize = decoder->shn_get_buffer_block_size(512);
|
||||
buffer = malloc(bufferSize);
|
||||
|
||||
unsigned int length;
|
||||
int chan;
|
||||
float freq;
|
||||
int bps;
|
||||
|
||||
decoder->file_info(NULL, &chan, &freq, NULL, &bps, NULL);
|
||||
|
||||
/*NSLog(@"chan: %d",chan);
|
||||
NSLog(@"freq: %f",freq);
|
||||
NSLog(@"bps: %d",bps);*/
|
||||
|
||||
channels = chan;
|
||||
frequency = (int)freq;
|
||||
bitsPerSample = bps;
|
||||
|
||||
/*NSLog(@"channels: %d",channels);
|
||||
NSLog(@"frequency: %f",(double)frequency);
|
||||
NSLog(@"bitsPerSample: %d",bitsPerSample);*/
|
||||
|
||||
length = decoder->shn_get_song_length();
|
||||
//NSLog(@"length: %d",length);
|
||||
totalSize = (((double)(length)*frequency)/1000.0) * channels * (bitsPerSample/8);
|
||||
bitrate = (int)((double)totalSize/((double)length/1000.0));
|
||||
|
||||
/*NSLog(@"totalSize: %d",totalSize);
|
||||
NSLog(@"bitrate: %d",bitrate);*/
|
||||
|
||||
decoder->go();
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (int)fillBuffer:(void *)buf ofSize:(UInt32)size
|
||||
{
|
||||
|
||||
//long numread = bufferAmount;
|
||||
//long count = 0;
|
||||
long numread, count;
|
||||
bufferAmount = 0;
|
||||
inputBuffer = malloc(bufferSize);
|
||||
|
||||
//Fill from buffer, going by bufferAmount
|
||||
//if still needs more, decode and repeat
|
||||
if (bufferAmount == 0)
|
||||
{
|
||||
//bufferAmount = shn_read(handle, buffer, bufferSize);
|
||||
while((bufferAmount = decoder->read(inputBuffer, bufferSize)) == (unsigned)(-1))
|
||||
{
|
||||
bufferAmount = decoder->read(inputBuffer, bufferSize);
|
||||
}
|
||||
if (bufferAmount == 0)
|
||||
return 0;
|
||||
else if(bufferAmount == (unsigned)( -2))
|
||||
{
|
||||
//NSLog(@"closing file, eof");
|
||||
return -2;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(buffer, inputBuffer, bufferAmount);
|
||||
free(inputBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
//NSLog(@"bufferAmount: %d",bufferAmount);
|
||||
|
||||
|
||||
count = bufferAmount;
|
||||
if (bufferAmount > size)
|
||||
{
|
||||
count = size;
|
||||
}
|
||||
|
||||
memcpy(buf, buffer, count);
|
||||
|
||||
bufferAmount -= count;
|
||||
|
||||
if (bufferAmount > 0)
|
||||
memmove(buffer, (&((char *)buffer)[count]), bufferAmount);
|
||||
|
||||
if (count < size)
|
||||
numread = [self fillBuffer:(&((char *)buf)[count]) ofSize:(size - count)];
|
||||
else
|
||||
numread = 0;
|
||||
|
||||
return count + numread;
|
||||
}
|
||||
|
||||
- (double)seekToTime:(double)milliseconds
|
||||
{
|
||||
unsigned int sec;
|
||||
|
||||
/*if (!shn_seekable(handle))
|
||||
return -1.0;*/
|
||||
|
||||
sec = (int)(milliseconds/1000.0);
|
||||
|
||||
//shn_seek(handle, sec);
|
||||
|
||||
decoder->seek(sec);
|
||||
|
||||
return (sec * 1000.0);
|
||||
}
|
||||
|
||||
- (void)close
|
||||
{
|
||||
if(decoder)
|
||||
{
|
||||
decoder->exit();
|
||||
delete decoder;
|
||||
decoder = NULL;
|
||||
}
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
free(buffer);
|
||||
buffer = NULL;
|
||||
}
|
||||
|
||||
/*if (shn_cleanup_decoder(handle))
|
||||
shn_unload(handle);*/
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,64 +0,0 @@
|
|||
//
|
||||
// SoundFile.h
|
||||
// Cog
|
||||
//
|
||||
// Created by Vincent Spader on 1/15/05.
|
||||
// Copyright 2005 Vincent Spader All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import <CoreAudio/AudioHardware.h>
|
||||
#import <AudioToolbox/AudioToolbox.h>
|
||||
#import <AudioUnit/AudioUnit.h>
|
||||
|
||||
#import "DBLog.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
BOOL hostIsBigEndian();
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@interface SoundFile : NSObject {
|
||||
UInt16 bitsPerSample;
|
||||
UInt16 channels;
|
||||
UInt32 frequency;
|
||||
UInt32 bitrate;
|
||||
BOOL isBigEndian;
|
||||
BOOL isUnsigned;
|
||||
|
||||
unsigned long totalSize;
|
||||
}
|
||||
|
||||
- (unsigned long)totalSize;
|
||||
|
||||
- (double)length;
|
||||
|
||||
- (int)bitrate;
|
||||
|
||||
+ (SoundFile *)soundFileFromFilename:(NSString *)filename; //PRIVATE
|
||||
+ (SoundFile *)open:(NSString *)filename;
|
||||
+ (SoundFile *)readInfo:(NSString *)filename;
|
||||
|
||||
- (BOOL)open:(const char *)filename;
|
||||
- (void)getFormat:(AudioStreamBasicDescription *)sourceStreamFormat;
|
||||
|
||||
- (BOOL)readInfo:(const char *)filename; //for getting information
|
||||
|
||||
- (int)fillBuffer:(void *)buf ofSize:(UInt32)size;
|
||||
|
||||
//- (BOOL)seek:(unsigned long)position;
|
||||
- (double)seekToTime:(double)milliseconds;
|
||||
- (void)close;
|
||||
- (void)reset; //START AGAIN
|
||||
|
||||
- (UInt16)channels;
|
||||
- (UInt16)bitsPerSample;
|
||||
- (UInt32)frequency;
|
||||
-(BOOL)isBigEndian;
|
||||
-(BOOL)isUnsigned;
|
||||
|
||||
@end
|
|
@ -1,260 +0,0 @@
|
|||
//
|
||||
// SoundFile.m
|
||||
// Cog
|
||||
//
|
||||
// Created by Vincent Spader on 1/15/05.
|
||||
// Copyright 2005 Vincent Spader All rights reserved.
|
||||
//
|
||||
|
||||
#import "SoundFile.h"
|
||||
|
||||
#import "FlacFile.h"
|
||||
//#import "AACFile.h"
|
||||
#import "MonkeysFile.h"
|
||||
//#import "MPEGFile.h"
|
||||
#import "MusepackFile.h"
|
||||
#import "VorbisFile.h"
|
||||
//#import "WaveFile.h"
|
||||
#import "WavPackFile.h"
|
||||
#import "ShnFile.h"
|
||||
#import "CoreAudioFile.h"
|
||||
//#import "GameFile.h"
|
||||
#import "MadFile.h"
|
||||
|
||||
|
||||
//Something is redefining BOOL
|
||||
#undef BOOL
|
||||
|
||||
extern "C" {
|
||||
BOOL hostIsBigEndian()
|
||||
{
|
||||
#ifdef __BIG_ENDIAN__
|
||||
return YES;
|
||||
#else
|
||||
return NO;
|
||||
#endif
|
||||
}
|
||||
|
||||
extern NSArray * getCoreAudioExtensions();
|
||||
|
||||
};
|
||||
|
||||
@implementation SoundFile
|
||||
|
||||
/*- (void)seek:(unsigned long)position
|
||||
{
|
||||
unsigned long time;
|
||||
unsigned long frame;
|
||||
|
||||
frame = position/channels/(bitsPerSample/8);
|
||||
time = (unsigned long)(((double)frame/(frequency/1000.0)));
|
||||
|
||||
currentPosition = position;
|
||||
|
||||
time = [self seekToTime:time];
|
||||
position = time * (frequency/1000.0)*chanels*(bitsPerSample/8)
|
||||
}
|
||||
*/
|
||||
- (double)length
|
||||
{
|
||||
return (totalSize/channels/(bitsPerSample/8)/(frequency/1000.0));
|
||||
}
|
||||
|
||||
- (int)bitrate
|
||||
{
|
||||
return bitrate;
|
||||
}
|
||||
|
||||
//this should be done by the soundfile....not seek...
|
||||
- (double)seekToTime:(double)milliseconds
|
||||
{
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@class FlacFile;
|
||||
@class MonkeysFile;
|
||||
@class MPEGFile;
|
||||
@class MusepackFile;
|
||||
@class VorbisFile;
|
||||
@class WaveFile;
|
||||
@class AACFile;
|
||||
@class WavPackFile;
|
||||
@class ShnFile;
|
||||
*/
|
||||
+ (SoundFile *)soundFileFromFilename:(NSString *)filename
|
||||
{
|
||||
SoundFile *soundFile;
|
||||
NSString *extension;
|
||||
DBLog(@"Filename: %@", filename);
|
||||
|
||||
extension = [filename pathExtension];
|
||||
|
||||
/*if (([[filename pathExtension] caseInsensitiveCompare:@"wav"] == NSOrderedSame) || ([[filename pathExtension] caseInsensitiveCompare:@"aiff"] == NSOrderedSame) || ([[filename pathExtension] caseInsensitiveCompare:@"aif"] == NSOrderedSame))
|
||||
{
|
||||
soundFile = [[WaveFile alloc] init];
|
||||
}*/
|
||||
if ([[filename pathExtension] caseInsensitiveCompare:@"ogg"] == NSOrderedSame)
|
||||
{
|
||||
soundFile = [[VorbisFile alloc] init];
|
||||
}
|
||||
else if ([[filename pathExtension] caseInsensitiveCompare:@"mpc"] == NSOrderedSame)
|
||||
{
|
||||
soundFile = [[MusepackFile alloc] init];
|
||||
}
|
||||
else if ([[filename pathExtension] caseInsensitiveCompare:@"flac"] == NSOrderedSame)
|
||||
{
|
||||
soundFile = [[FlacFile alloc] init];
|
||||
}
|
||||
else if ([[filename pathExtension] caseInsensitiveCompare:@"ape"] == NSOrderedSame)
|
||||
{
|
||||
soundFile = [[MonkeysFile alloc] init];
|
||||
}
|
||||
else if ([[filename pathExtension] caseInsensitiveCompare:@"mp3"] == NSOrderedSame)
|
||||
{
|
||||
soundFile = [[MADFile alloc] init];
|
||||
}
|
||||
/*else if ([[filename pathExtension] caseInsensitiveCompare:@"aac"] == NSOrderedSame)
|
||||
{
|
||||
soundFile = [[AACFile alloc] init];
|
||||
}*/
|
||||
else if ([[filename pathExtension] caseInsensitiveCompare:@"wv"] == NSOrderedSame)
|
||||
{
|
||||
soundFile = [[WavPackFile alloc] init];
|
||||
}
|
||||
else if ([[filename pathExtension] caseInsensitiveCompare:@"shn"] == NSOrderedSame)
|
||||
{
|
||||
soundFile = [[ShnFile alloc] init];
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned i;
|
||||
NSArray *extensions = getCoreAudioExtensions();
|
||||
|
||||
soundFile = nil;
|
||||
|
||||
for(i = 0; i < [extensions count]; ++i) {
|
||||
if([[extensions objectAtIndex:i] caseInsensitiveCompare:extension]) {
|
||||
soundFile = [[CoreAudioFile alloc] init];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return soundFile;
|
||||
}
|
||||
|
||||
+ (SoundFile *)open:(NSString *)filename
|
||||
{
|
||||
SoundFile *soundFile;
|
||||
BOOL b;
|
||||
|
||||
soundFile = [SoundFile soundFileFromFilename:filename];
|
||||
|
||||
b = [soundFile open:[filename UTF8String]];
|
||||
if (b == YES)
|
||||
return soundFile;
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (SoundFile *)readInfo:(NSString *)filename
|
||||
{
|
||||
BOOL b;
|
||||
SoundFile *soundFile;
|
||||
|
||||
soundFile = [SoundFile soundFileFromFilename:filename];
|
||||
|
||||
b = [soundFile readInfo:[filename UTF8String]];
|
||||
if (b == NO)
|
||||
return nil;
|
||||
|
||||
[soundFile close];
|
||||
|
||||
return soundFile;
|
||||
}
|
||||
|
||||
- (void)reset
|
||||
{
|
||||
[self seekToTime:0.0];
|
||||
}
|
||||
|
||||
- (void)getFormat:(AudioStreamBasicDescription *)sourceStreamFormat
|
||||
{
|
||||
// NSLog(@"Getting format!");
|
||||
sourceStreamFormat->mFormatID = kAudioFormatLinearPCM;
|
||||
sourceStreamFormat->mFormatFlags = 0;
|
||||
|
||||
sourceStreamFormat->mSampleRate = frequency;
|
||||
|
||||
sourceStreamFormat->mBitsPerChannel = bitsPerSample;
|
||||
|
||||
sourceStreamFormat->mBytesPerFrame = (bitsPerSample/8)*channels;
|
||||
sourceStreamFormat->mChannelsPerFrame = channels;
|
||||
|
||||
sourceStreamFormat->mFramesPerPacket = 1;
|
||||
sourceStreamFormat->mBytesPerPacket = (bitsPerSample/8)*channels;
|
||||
sourceStreamFormat->mReserved = 0;
|
||||
|
||||
if (isBigEndian == YES)
|
||||
{
|
||||
sourceStreamFormat->mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
|
||||
sourceStreamFormat->mFormatFlags |= kLinearPCMFormatFlagIsAlignedHigh;
|
||||
// sourceStreamFormat->mFormatFlags |= kLinearPCMFormatFlagIsNonMixable;
|
||||
// NSLog(@"FUCKER IS BIG ENDIAN");
|
||||
}
|
||||
if (isUnsigned == NO)
|
||||
sourceStreamFormat->mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
|
||||
}
|
||||
|
||||
- (void)close
|
||||
{
|
||||
}
|
||||
|
||||
- (int)fillBuffer:(void *)buf ofSize:(UInt32)size
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (BOOL)open:(const char *)filename
|
||||
{
|
||||
// NSLog(@"WRONG OPEN!!!");
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)readInfo:(const char *)filename
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (unsigned long)totalSize
|
||||
{
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
- (UInt16)channels
|
||||
{
|
||||
return channels;
|
||||
}
|
||||
|
||||
- (UInt16)bitsPerSample
|
||||
{
|
||||
return bitsPerSample;
|
||||
}
|
||||
|
||||
- (UInt32)frequency
|
||||
{
|
||||
return frequency;
|
||||
}
|
||||
|
||||
-(BOOL)isBigEndian
|
||||
{
|
||||
return isBigEndian;
|
||||
}
|
||||
-(BOOL)isUnsigned
|
||||
{
|
||||
return isUnsigned;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,28 +0,0 @@
|
|||
//
|
||||
// VorbisFile.h
|
||||
// zyVorbis
|
||||
//
|
||||
// Created by Vincent Spader on 1/22/05.
|
||||
// Copyright 2005 Vincent Spader All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "SoundFile.h"
|
||||
|
||||
//config.h things
|
||||
#define __MACOSX__
|
||||
#define HAVE_CONFIG_H
|
||||
|
||||
#import <Vorbis/vorbisfile.h>
|
||||
#import <Vorbis/codec.h>
|
||||
|
||||
#undef __MACOSX__
|
||||
#undef HAVE_CONFIG_H
|
||||
|
||||
@interface VorbisFile : SoundFile {
|
||||
FILE *inFd;
|
||||
OggVorbis_File vorbisRef;
|
||||
int currentSection;
|
||||
}
|
||||
- (BOOL)readInfo;
|
||||
@end
|
|
@ -1,79 +0,0 @@
|
|||
//
|
||||
// VorbisFile.m
|
||||
// zyVorbis
|
||||
//
|
||||
// Created by Vincent Spader on 1/22/05.
|
||||
// Copyright 2005 Vincent Spader All rights reserved.
|
||||
//
|
||||
|
||||
#import "VorbisFile.h"
|
||||
|
||||
|
||||
@implementation VorbisFile
|
||||
|
||||
- (BOOL)open:(const char *)filename
|
||||
{
|
||||
inFd = fopen(filename, "rb");
|
||||
if (inFd == 0)
|
||||
return NO;
|
||||
|
||||
if (ov_open(inFd, &vorbisRef, NULL, 0) != 0)
|
||||
return NO;
|
||||
|
||||
return [self readInfo];
|
||||
}
|
||||
|
||||
- (BOOL)readInfo
|
||||
{
|
||||
vorbis_info *vi;
|
||||
|
||||
vi = ov_info(&vorbisRef, -1);
|
||||
bitrate = (int)(vi->bitrate_nominal/1000.0);
|
||||
channels = vi->channels;
|
||||
bitsPerSample = vi->channels * 8;
|
||||
frequency = vi->rate;
|
||||
|
||||
totalSize = ov_pcm_total(&vorbisRef, -1) * channels * bitsPerSample/8;
|
||||
|
||||
// DBLog(@"Ok to go WITH OGG.");
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)readInfo:(const char *)filename
|
||||
{
|
||||
[self open:filename]; //automatically invokes readInfo
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (int)fillBuffer:(void *)buf ofSize:(UInt32)size
|
||||
{
|
||||
int numread;
|
||||
int total = 0;
|
||||
|
||||
numread = ov_read(&vorbisRef, &((char *)buf)[total], size - total, 0, bitsPerSample/8, 1, ¤tSection);
|
||||
while (total != size && numread > 0)
|
||||
{
|
||||
total += numread;
|
||||
|
||||
numread = ov_read(&vorbisRef, &((char *)buf)[total], size - total, 0, bitsPerSample/8, 1, ¤tSection);
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
- (void)close
|
||||
{
|
||||
ov_clear(&vorbisRef);
|
||||
}
|
||||
|
||||
- (double)seekToTime:(double)milliseconds
|
||||
{
|
||||
ov_time_seek(&vorbisRef, (double)milliseconds/1000.0);
|
||||
|
||||
return milliseconds;
|
||||
}
|
||||
|
||||
|
||||
@end
|
|
@ -1,18 +0,0 @@
|
|||
//
|
||||
// WavPackFile.h
|
||||
// Cog
|
||||
//
|
||||
// Created by Vincent Spader on 6/6/05.
|
||||
// Copyright 2005 Vincent Spader All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "SoundFile.h"
|
||||
|
||||
#import "Wavpack/wputils.h"
|
||||
|
||||
@interface WavPackFile : SoundFile {
|
||||
WavpackContext *wpc;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,86 +0,0 @@
|
|||
//
|
||||
// WavPackFile.m
|
||||
// Cog
|
||||
//
|
||||
// Created by Vincent Spader on 6/6/05.
|
||||
// Copyright 2005 Vincent Spader All rights reserved.
|
||||
//
|
||||
|
||||
#import "WavPackFile.h"
|
||||
|
||||
|
||||
@implementation WavPackFile
|
||||
|
||||
- (BOOL)open:(const char *)filename
|
||||
{
|
||||
int open_flags = 0;
|
||||
char error[80];
|
||||
|
||||
wpc = WavpackOpenFileInput(filename, error, open_flags, 0);
|
||||
if (!wpc)
|
||||
return NO;
|
||||
|
||||
channels = WavpackGetNumChannels(wpc);
|
||||
bitsPerSample = WavpackGetBitsPerSample(wpc);
|
||||
// bitsPerSample = 32;
|
||||
NSLog(@"BYTES PER SAMPLE: %i", WavpackGetBitsPerSample(wpc));
|
||||
NSLog(@"BYTES PER SAMPLE: %i", WavpackGetBytesPerSample(wpc));
|
||||
|
||||
frequency = WavpackGetSampleRate(wpc);
|
||||
|
||||
int samples;
|
||||
samples = WavpackGetNumSamples(wpc);
|
||||
totalSize = samples * channels * (bitsPerSample/8);
|
||||
|
||||
bitrate = (int)(WavpackGetAverageBitrate(wpc, TRUE)/1000.0);
|
||||
|
||||
isBigEndian = hostIsBigEndian();
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)readInfo:(const char *)filename
|
||||
{
|
||||
[self open:filename]; //does the same damn thing
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (int)fillBuffer:(void *)buf ofSize:(UInt32)size
|
||||
{
|
||||
int numsamples;
|
||||
int n;
|
||||
void *sampleBuf = malloc(size*2);
|
||||
|
||||
numsamples = size/(bitsPerSample/8)/channels;
|
||||
// DBLog(@"NUM SAMPLES: %i %i", numsamples, size);
|
||||
n = WavpackUnpackSamples(wpc, sampleBuf, numsamples);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < n*channels; i++)
|
||||
{
|
||||
((UInt16 *)buf)[i] = ((UInt32 *)sampleBuf)[i];
|
||||
}
|
||||
n *= (bitsPerSample/8)*channels;
|
||||
|
||||
free(sampleBuf);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
- (double)seekToTime:(double)milliseconds
|
||||
{
|
||||
int sample;
|
||||
sample = frequency*(milliseconds/1000.0);
|
||||
|
||||
WavpackSeekSample(wpc, sample);
|
||||
|
||||
return milliseconds;
|
||||
}
|
||||
|
||||
- (void)close
|
||||
{
|
||||
WavpackCloseFile(wpc);
|
||||
}
|
||||
|
||||
@end
|
Loading…
Reference in New Issue