cog/Plugins/Musepack/MusepackDecoder.m

232 lines
4.7 KiB
Matlab
Raw Normal View History

2005-06-02 18:16:43 +00:00
//
// MusepackFile.m
// zyVorbis
//
// Created by Vincent Spader on 1/23/05.
2005-07-02 21:02:06 +00:00
// Copyright 2005 Vincent Spader All rights reserved.
2005-06-02 18:16:43 +00:00
//
#import "MusepackDecoder.h"
2005-06-02 18:16:43 +00:00
@implementation MusepackDecoder
2005-06-02 18:16:43 +00:00
mpc_int32_t ReadProc(void *data, void *ptr, mpc_int32_t size)
2005-06-02 18:16:43 +00:00
{
MusepackDecoder *decoder = (MusepackDecoder *) data;
return [[decoder source] read:ptr amount:size];
}
mpc_bool_t SeekProc(void *data, mpc_int32_t offset)
{
MusepackDecoder *decoder = (MusepackDecoder *) data;
2007-07-11 01:20:32 +00:00
return [[decoder source] seek:offset whence:SEEK_SET];
}
mpc_int32_t TellProc(void *data)
{
MusepackDecoder *decoder = (MusepackDecoder *) data;
return [[decoder source] tell];
}
mpc_int32_t GetSizeProc(void *data)
{
MusepackDecoder *decoder = (MusepackDecoder *) data;
2005-06-02 18:16:43 +00:00
if ([[decoder source] seekable]) {
long currentPos = [[decoder source] tell];
[[decoder source] seek:0 whence:SEEK_END];
long size = [[decoder source] tell];
[[decoder source] seek:currentPos whence:SEEK_SET];
return size;
}
else {
return 0;
}
}
2005-06-02 18:16:43 +00:00
mpc_bool_t CanSeekProc(void *data)
{
MusepackDecoder *decoder = (MusepackDecoder *) data;
return [[decoder source] seekable];
}
- (BOOL)open:(id<CogSource>)s
{
[self setSource: s];
reader.read = ReadProc;
reader.seek = SeekProc;
reader.tell = TellProc;
reader.get_size = GetSizeProc;
reader.canseek = CanSeekProc;
reader.data = self;
2005-06-02 18:16:43 +00:00
mpc_streaminfo_init(&info);
if (mpc_streaminfo_read(&info, &reader) != ERROR_CODE_OK)
2005-06-02 18:16:43 +00:00
{
NSLog(@"Not a valid musepack file.");
2005-06-02 18:16:43 +00:00
return NO;
}
/* instantiate a decoder with our reader */
mpc_decoder_setup(&decoder, &reader);
if (!mpc_decoder_initialize(&decoder, &info))
{
NSLog(@"Error initializing decoder.");
return NO;
}
2005-06-02 18:16:43 +00:00
2006-06-19 00:39:41 +00:00
bitrate = (int)(info.average_bitrate/1000.0);
2005-06-02 18:16:43 +00:00
frequency = info.sample_freq;
totalFrames = mpc_streaminfo_get_length_samples(&info);
2005-06-29 15:28:20 +00:00
[self willChangeValueForKey:@"properties"];
[self didChangeValueForKey:@"properties"];
2005-06-02 18:16:43 +00:00
return YES;
}
- (BOOL)writeToBuffer:(uint16_t *)sample_buffer fromBuffer:(const MPC_SAMPLE_FORMAT *)p_buffer frames:(unsigned)frames
2005-06-02 18:16:43 +00:00
{
unsigned n;
int m_bps = 16;
int clip_min = - 1 << (m_bps - 1),
2005-06-02 18:16:43 +00:00
clip_max = (1 << (m_bps - 1)) - 1,
float_scale = 1 << (m_bps - 1);
unsigned p_size = frames * 2; //2 = bits per sample
2005-06-02 18:16:43 +00:00
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;
}
// m_data_bytes_written += p_size * (m_bps >> 3);
return YES;
2005-06-02 18:16:43 +00:00
}
- (int)readAudio:(void *)buf frames:(UInt32)frames
2005-06-02 18:16:43 +00:00
{
MPC_SAMPLE_FORMAT sampleBuffer[MPC_DECODER_BUFFER_LENGTH];
int framesRead = 0;
int bytesPerFrame = 4; //bitsPerSample == 16, channels == 2
while (framesRead < frames)
{
//Fill from buffer, going by bufferFrames
//if still needs more, decode and repeat
if (bufferFrames == 0)
2005-06-02 18:16:43 +00:00
{
/* returns the length of the samples*/
unsigned status = mpc_decoder_decode(&decoder, sampleBuffer, 0, 0);
if (status == (unsigned)( -1))
{
//decode error
NSLog(@"Decode error");
return 0;
}
else if (status == 0) //EOF
{
return 0;
}
else //status>0 /* status == MPC_FRAME_LENGTH */
{
}
bufferFrames = status;
2005-06-02 18:16:43 +00:00
}
int framesToRead = bufferFrames;
if (bufferFrames > frames)
2005-06-02 18:16:43 +00:00
{
framesToRead = frames;
2005-06-02 18:16:43 +00:00
}
[self writeToBuffer:((uint16_t*)(buf + (framesRead*bytesPerFrame))) fromBuffer:sampleBuffer frames: bufferFrames];
frames -= framesToRead;
framesRead += framesToRead;
bufferFrames -= framesToRead;
if (bufferFrames > 0)
2005-06-02 18:16:43 +00:00
{
memmove((uint8_t *)sampleBuffer, ((uint8_t *)sampleBuffer) + (framesToRead * bytesPerFrame), bufferFrames * bytesPerFrame);
2005-06-02 18:16:43 +00:00
}
}
return framesRead;
2005-06-02 18:16:43 +00:00
}
- (void)close
{
[source close];
2005-06-02 18:16:43 +00:00
}
- (long)seek:(long)sample
2005-06-02 18:16:43 +00:00
{
mpc_decoder_seek_sample(&decoder, sample);
return sample;
2005-06-02 18:16:43 +00:00
}
- (void)setSource:(id<CogSource>)s
{
[s retain];
[source release];
source = s;
}
- (id<CogSource>)source
{
return source;
}
- (NSDictionary *)properties
2005-06-02 18:16:43 +00:00
{
return [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:bitrate], @"bitrate",
[NSNumber numberWithFloat:frequency], @"sampleRate",
[NSNumber numberWithDouble:totalFrames], @"totalFrames",
[NSNumber numberWithInt:16], @"bitsPerSample",
[NSNumber numberWithInt:2], @"channels",
[NSNumber numberWithBool:[source seekable]], @"seekable",
@"host",@"endian",
nil];
2005-06-02 18:16:43 +00:00
}
+ (NSArray *)fileTypes
2005-06-02 18:16:43 +00:00
{
return [NSArray arrayWithObject:@"mpc"];
2005-06-02 18:16:43 +00:00
}
2007-10-14 18:39:58 +00:00
+ (NSArray *)mimeTypes
{
return [NSArray arrayWithObjects:@"audio/x-musepack", nil];
}
2005-06-02 18:16:43 +00:00
@end