Implemented floating point sample format support into CogAudio and all relevant plug-ins

CQTexperiment
Chris Moeller 2013-10-05 14:15:09 -07:00
parent b16ccd59f7
commit 74b6188772
17 changed files with 227 additions and 262 deletions

View File

@ -23,6 +23,7 @@
int bytesPerSample;
int bytesPerFrame;
int volumeScale;
BOOL floatingPoint;
BOOL swapEndian;
BOOL shouldSeek;

View File

@ -54,6 +54,8 @@ static BOOL hostIsBigEndian()
swapEndian = NO;
}
floatingPoint = [[properties objectForKey:@"floatingPoint"] boolValue];
[self refreshVolumeScaling];
shouldContinue = YES;
@ -186,6 +188,34 @@ static int32_t swap_32(uint32_t input)
return (input >> 24) | ((input >> 8) & 0xff00) | ((input << 8) & 0xff0000) | (input << 24);
}
static float swap_32f(float input)
{
union {
float f;
int32_t i;
} val;
val.f = input;
val.i = swap_32(val.i);
return val.f;
}
static int64_t swap_64(uint64_t input)
{
return (input >> 56) | ((input >> 40) & 0xff00) | ((input >> 24) & 0xff0000) | ((input >> 8) & 0xff000000) |
((input << 8) & 0xff00000000) | ((input << 24) & 0xff0000000000) | ((input << 40) & 0xff000000000000) | (input << 56);
}
static double swap_64f(double input)
{
union {
double f;
int64_t i;
} val;
val.f = input;
val.i = swap_64(val.i);
return val.f;
}
- (void)process
{
int amountInBuffer = 0;
@ -276,19 +306,70 @@ static int32_t swap_32(uint32_t input)
break;
case 4:
{
int32_t * samples = (int32_t *)inputBuffer;
for (int i = 0; i < totalFrames; i++)
if (floatingPoint)
{
int64_t sample = samples[i];
if (swapEndian) sample = swap_32(sample);
sample = (sample * volumeScale) >> 12;
if ((unsigned)(sample + 0x80000000) & 0xffffffff00000000) sample = (sample >> 63) ^ 0x7fffffff;
if (swapEndian) sample = swap_32(sample);
samples[i] = sample;
float * samples = (float *)inputBuffer;
float scale = (float)volumeScale / 4096;
for (int i = 0; i < totalFrames; i++)
{
float sample = samples[i];
if (swapEndian) sample = swap_32f(sample);
sample *= scale;
if (swapEndian) sample = swap_32f(sample);
samples[i] = sample;
}
}
}
break;
else
{
int32_t * samples = (int32_t *)inputBuffer;
for (int i = 0; i < totalFrames; i++)
{
int64_t sample = samples[i];
if (swapEndian) sample = swap_32(sample);
sample = (sample * volumeScale) >> 12;
if ((unsigned)(sample + 0x80000000) & 0xffffffff00000000) sample = (sample >> 63) ^ 0x7fffffff;
if (swapEndian) sample = swap_32(sample);
samples[i] = sample;
}
}
break;
case 8:
if (floatingPoint)
{
double * samples = (double *)inputBuffer;
double scale = (double)volumeScale / 4096;
for (int i = 0; i < totalFrames; i++)
{
double sample = samples[i];
if (swapEndian) sample = swap_64f(sample);
sample *= scale;
if (swapEndian) sample = swap_64f(sample);
samples[i] = sample;
}
}
else
{
int64_t * samples = (int64_t *)inputBuffer;
for (int i = 0; i < totalFrames; i++)
{
int64_t sample = samples[i];
if (swapEndian) sample = swap_64(sample);
int64_t high_part = sample >> (32 + 12);
int64_t low_part = (sample & 0xffffffff) | (sample >> 31);
high_part *= volumeScale;
low_part = (low_part * volumeScale) >> 12;
if (((uint64_t)low_part + 0x100000000) & 0xfffffffe00000000)
high_part += low_part >> 32;
if (((uint64_t)high_part + 0x80000000) & 0xffffffff00000000)
sample = high_part >> 63;
else
sample = (high_part << 32) | (low_part & 0xffffffff);
if (swapEndian) sample = swap_64(sample);
samples[i] = sample;
}
}
break;
}
}

View File

@ -47,6 +47,8 @@ AudioStreamBasicDescription propertiesToASBD(NSDictionary *properties)
asbd.mFramesPerPacket = 1;
asbd.mBytesPerPacket = asbd.mBytesPerFrame * asbd.mFramesPerPacket;
asbd.mReserved = 0;
BOOL isFloat = [[properties objectForKey:@"floatingPoint"] boolValue];
if ([[properties objectForKey:@"endian"] isEqualToString:@"big"] || ([[properties objectForKey:@"endian"] isEqualToString:@"host"] && hostIsBigEndian() ))
{
@ -54,9 +56,13 @@ AudioStreamBasicDescription propertiesToASBD(NSDictionary *properties)
asbd.mFormatFlags |= kLinearPCMFormatFlagIsAlignedHigh;
}
if ([[properties objectForKey:@"unsigned"] boolValue] == NO) {
if (isFloat == NO && [[properties objectForKey:@"unsigned"] boolValue] == NO) {
asbd.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
}
if (isFloat) {
asbd.mFormatFlags |= kLinearPCMFormatFlagIsFloat | kAudioFormatFlagIsPacked;
}
return asbd;
}

View File

@ -45,6 +45,7 @@
int bitrate;
int channels;
int bitsPerSample;
BOOL floatingPoint;
float sampleRate;
NSString *endian;
@ -100,6 +101,7 @@
@property int bitrate;
@property int channels;
@property int bitsPerSample;
@property BOOL floatingPoint;
@property float sampleRate;
@property float replayGainAlbumGain;

View File

@ -38,6 +38,7 @@
@synthesize bitrate;
@synthesize channels;
@synthesize bitsPerSample;
@synthesize floatingPoint;
@synthesize sampleRate;
@synthesize replayGainAlbumGain;

View File

@ -31,6 +31,7 @@
int bitrate;
int bitsPerSample;
BOOL floatingPoint;
int channels;
float frequency;
long totalFrames;

View File

@ -84,10 +84,12 @@
bitsPerSample = asbd.mBitsPerChannel;
channels = asbd.mChannelsPerFrame;
frequency = asbd.mSampleRate;
floatingPoint = NO;
// mBitsPerChannel will only be set for lpcm formats
if(0 == bitsPerSample) {
bitsPerSample = 16;
bitsPerSample = 32;
floatingPoint = YES;
}
// Set output format
@ -96,7 +98,12 @@
bzero(&result, sizeof(AudioStreamBasicDescription));
result.mFormatID = kAudioFormatLinearPCM;
result.mFormatFlags = kAudioFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsBigEndian;
if (floatingPoint) {
result.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked;
}
else {
result.mFormatFlags = kAudioFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsBigEndian;
}
result.mSampleRate = frequency;
result.mChannelsPerFrame = channels;
@ -177,11 +184,12 @@
return [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:channels],@"channels",
[NSNumber numberWithInt:bitsPerSample],@"bitsPerSample",
[NSNumber numberWithBool:floatingPoint],@"floatingPoint",
[NSNumber numberWithInt:bitrate],@"bitrate",
[NSNumber numberWithFloat:frequency],@"sampleRate",
[NSNumber numberWithLong:totalFrames],@"totalFrames",
[NSNumber numberWithBool:YES], @"seekable",
@"big", @"endian",
floatingPoint ? @"host" : @"big", @"endian",
nil];
}

View File

@ -18,7 +18,8 @@ extern DUMBFILE *dumbfile_open_memory_and_free(char *data, long size);
@interface DumbDecoder : NSObject <CogDecoder> {
DUH *duh;
DUH_SIGRENDERER *dsr;
sample_t **sampptr;
id<CogSource> source;
long length;

View File

@ -185,6 +185,8 @@ int callbackLoop(void *data)
loops = 0;
fadeTotal = fadeRemain = 44100 * 8;
sampptr = allocate_sample_buffer(2, 1024);
[self willChangeValueForKey:@"properties"];
[self didChangeValueForKey:@"properties"];
@ -197,7 +199,8 @@ int callbackLoop(void *data)
[NSNumber numberWithInt:0], @"bitrate",
[NSNumber numberWithFloat:44100], @"sampleRate",
[NSNumber numberWithDouble:((length / 65.536f)*44.1000)], @"totalFrames",
[NSNumber numberWithInt:16], @"bitsPerSample", //Samples are short
[NSNumber numberWithInt:32], @"bitsPerSample", //Samples are short
[NSNumber numberWithBool:YES], @"floatingPoint",
[NSNumber numberWithInt:2], @"channels", //output from gme_play is in stereo
[NSNumber numberWithBool:[source seekable]], @"seekable",
@"host", @"endian",
@ -206,27 +209,49 @@ int callbackLoop(void *data)
- (int)readAudio:(void *)buf frames:(UInt32)frames
{
int rendered = duh_render(dsr, 16 /* shorts */, 0 /* not unsigned */, 1.0 /* volume */, 65536.0f / 44100.0f /* 65536 hz? */, frames, buf);
if ( loops >= 2 ) {
int16_t * sampleBuf = ( int16_t * ) buf;
long fadeEnd = fadeRemain - rendered;
if ( fadeEnd < 0 )
fadeEnd = 0;
for ( long fadePos = fadeRemain; fadePos > fadeEnd; --fadePos ) {
long offset = (fadeRemain - fadePos) * 2;
int64_t sampleLeft = sampleBuf[ offset + 0 ];
int64_t sampleRight = sampleBuf[ offset + 1 ];
sampleLeft = (sampleLeft * fadePos) / fadeTotal;
sampleRight = (sampleRight * fadePos) / fadeTotal;
sampleBuf[ offset + 0 ] = sampleLeft;
sampleBuf[ offset + 1 ] = sampleRight;
int total = 0;
while ( total < frames ) {
int framesToRender = 1024;
if ( framesToRender > frames )
framesToRender = frames;
dumb_silence( sampptr[0], framesToRender * 2 );
int rendered = duh_sigrenderer_generate_samples( dsr, 1.0, 65536.0f / 44100.0f, framesToRender, sampptr );
if (rendered <= 0)
break;
for ( int i = 0; i < rendered * 2; i++ ) {
const float scale = 1.0 / 0x800000;
((float *)buf)[(total * 2) + i] = (float)sampptr[0][i] * scale;
}
rendered = fadeRemain - fadeEnd;
fadeRemain = fadeEnd;
if ( loops >= 2 ) {
float * sampleBuf = ( float * ) buf;
long fadeEnd = fadeRemain - rendered;
if ( fadeEnd < 0 )
fadeEnd = 0;
float fadePosf = (float)fadeRemain / fadeTotal;
const float fadeStep = 1.0 / fadeTotal;
for ( long fadePos = fadeRemain; fadePos > fadeEnd; --fadePos, fadePosf -= fadeStep ) {
long offset = (fadeRemain - fadePos) * 2;
float sampleLeft = sampleBuf[ offset + 0 ];
float sampleRight = sampleBuf[ offset + 1 ];
sampleLeft *= fadePosf;
sampleRight *= fadePosf;
sampleBuf[ offset + 0 ] = sampleLeft;
sampleBuf[ offset + 1 ] = sampleRight;
}
rendered = fadeRemain - fadeEnd;
fadeRemain = fadeEnd;
}
total += rendered;
if ( rendered < framesToRender )
break;
}
return rendered;
return total;
}
- (long)seek:(long)frame
@ -253,6 +278,11 @@ int callbackLoop(void *data)
- (void)cleanUp
{
if (sampptr) {
destroy_sample_buffer(sampptr);
sampptr = NULL;
}
if (dsr) {
duh_end_sigrenderer(dsr);
dsr = NULL;

View File

@ -14,26 +14,12 @@
#define INPUT_BUFFER_SIZE 5*8192
struct audio_dither {
mad_fixed_t error[3];
mad_fixed_t random;
};
struct audio_stats {
unsigned long clipped_samples;
mad_fixed_t peak_clipping;
mad_fixed_t peak_sample;
};
@interface MADDecoder : NSObject <CogDecoder>
{
struct mad_stream _stream;
struct mad_frame _frame;
struct mad_synth _synth;
struct audio_dither channel_dither[2];
struct audio_stats stats;
unsigned char _inputBuffer[INPUT_BUFFER_SIZE+MAD_BUFFER_GUARD];
unsigned char *_outputBuffer;
int _outputFrames;
@ -57,7 +43,6 @@ struct audio_stats {
int bytesPerFrame;
int channels;
int bitsPerSample;
float sampleRate;
int bitrate;
long totalFrames;

View File

@ -277,9 +277,7 @@
mad_frame_finish (&frame);
mad_stream_finish (&stream);
bitsPerSample = 24;
bytesPerFrame = (bitsPerSample/8) * channels;
bytesPerFrame = sizeof(float) * channels;
[_source seek:0 whence:SEEK_SET];
inputEOF = NO;
@ -321,121 +319,6 @@
return [self scanFile];
}
/*
* NAME: prng()
* DESCRIPTION: 32-bit pseudo-random number generator
*/
static inline
unsigned long prng(unsigned long state)
{
return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
}
// Clipping and rounding code from madplay(audio.c):
/*
* madplay - MPEG audio decoder and player
* Copyright (C) 2000-2004 Robert Leslie
*/
static inline signed long audio_linear_dither(unsigned int bits, mad_fixed_t sample,
struct audio_dither *dither,
struct audio_stats *stats)
{
unsigned int scalebits;
mad_fixed_t output, mask, random;
enum {
MIN = -MAD_F_ONE,
MAX = MAD_F_ONE - 1
};
/* noise shape */
sample += dither->error[0] - dither->error[1] + dither->error[2];
dither->error[2] = dither->error[1];
dither->error[1] = dither->error[0] / 2;
/* bias */
output = sample + (1L << (MAD_F_FRACBITS + 1 - bits - 1));
scalebits = MAD_F_FRACBITS + 1 - bits;
mask = (1L << scalebits) - 1;
/* dither */
random = prng(dither->random);
output += (random & mask) - (dither->random & mask);
dither->random = random;
/* clip */
if (output >= stats->peak_sample) {
if (output > MAX) {
++stats->clipped_samples;
if (output - MAX > stats->peak_clipping)
stats->peak_clipping = output - MAX;
output = MAX;
if (sample > MAX)
sample = MAX;
}
stats->peak_sample = output;
}
else if (output < -stats->peak_sample) {
if (output < MIN) {
++stats->clipped_samples;
if (MIN - output > stats->peak_clipping)
stats->peak_clipping = MIN - output;
output = MIN;
if (sample < MIN)
sample = MIN;
}
stats->peak_sample = -output;
}
/* quantize */
output &= ~mask;
/* error feedback */
dither->error[0] = sample - output;
/* scale */
return output >> scalebits;
}
// Clipping and rounding code from madplay(audio.c):
/*
* madplay - MPEG audio decoder and player
* Copyright (C) 2000-2004 Robert Leslie
*/
#if 0
static int32_t
audio_linear_round(unsigned int bits,
mad_fixed_t sample)
{
enum {
MIN = -MAD_F_ONE,
MAX = MAD_F_ONE - 1
};
/* round */
sample += (1L << (MAD_F_FRACBITS - bits));
/* clip */
if(MAX < sample)
sample = MAX;
else if(MIN > sample)
sample = MIN;
/* quantize and scale */
return sample >> (MAD_F_FRACBITS + 1 - bits);
}
#endif
// End madplay code
- (void)writeOutput
{
unsigned int startingSample = 0;
@ -489,32 +372,19 @@ audio_linear_round(unsigned int bits,
int ch;
int i;
int stride = bitsPerSample/8;
unsigned char *outputPtr = _outputBuffer;
float *outputPtr = (float *) _outputBuffer;
float scale = 1.0 / MAD_F_ONE;
// samples [0 ... n]
for(i = startingSample; i < sampleCount; i++)
{
// channels [0 .. n] in this case LRLRLRLR
for (ch = 0; ch < channels; ch++)
{
signed long sample = audio_linear_dither(bitsPerSample,
_synth.pcm.samples[ch][i],
&channel_dither[ch],
&stats);
if(bitsPerSample == 24)
{
outputPtr[0] = sample >> 16;
outputPtr[1] = sample >> 8;
outputPtr[2] = sample >> 0;
}
else
{
outputPtr[0] = sample >> 8;
outputPtr[1] = sample & 0xff;
}
outputPtr += stride;
float sample = _synth.pcm.samples[ch][i] * scale;
outputPtr[0] = sample;
outputPtr++;
}
}
@ -607,8 +477,7 @@ audio_linear_round(unsigned int bits,
if (![_source seekable]) {
sampleRate = _frame.header.samplerate;
channels = MAD_NCHANNELS(&_frame.header);
bitsPerSample = 16;
bytesPerFrame = (bitsPerSample/8) * channels;
bytesPerFrame = sizeof(float) * channels;
[self willChangeValueForKey:@"properties"];
[self didChangeValueForKey:@"properties"];
@ -701,12 +570,13 @@ audio_linear_round(unsigned int bits,
{
return [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:channels],@"channels",
[NSNumber numberWithInt:bitsPerSample],@"bitsPerSample",
[NSNumber numberWithInt:32],@"bitsPerSample",
[NSNumber numberWithBool:YES],@"floatingPoint",
[NSNumber numberWithFloat:sampleRate],@"sampleRate",
[NSNumber numberWithInt:bitrate],@"bitrate",
[NSNumber numberWithLong:totalFrames - (_startPadding + _endPadding)],@"totalFrames",
[NSNumber numberWithBool:[_source seekable]], @"seekable",
@"big", @"endian",
@"host", @"endian",
nil];
}

View File

@ -24,7 +24,7 @@
float frequency;
long totalFrames;
}
- (BOOL)writeToBuffer:(uint16_t *)sample_buffer fromBuffer:(const MPC_SAMPLE_FORMAT *)p_buffer frames:(unsigned)frames;
- (BOOL)writeToBuffer:(float *)sample_buffer fromBuffer:(const MPC_SAMPLE_FORMAT *)p_buffer frames:(unsigned)frames;
- (void)setSource:(id<CogSource>)s;
- (id<CogSource>)source;

View File

@ -95,30 +95,24 @@ mpc_bool_t CanSeekProc(void *data)
return YES;
}
- (BOOL)writeToBuffer:(uint16_t *)sample_buffer fromBuffer:(const MPC_SAMPLE_FORMAT *)p_buffer frames:(unsigned)frames
- (BOOL)writeToBuffer:(float *)sample_buffer fromBuffer:(const MPC_SAMPLE_FORMAT *)p_buffer frames:(unsigned)frames
{
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);
unsigned p_size = frames * 2; //2 = bits per sample
unsigned p_size = frames * 2; //2 = stereo
#ifdef MPC_FIXED_POINT
const float float_scale = 1.0 / MPC_FIXED_POINT_SCALE;
#endif
for (n = 0; n < p_size; n++)
{
int val;
float val;
#ifdef MPC_FIXED_POINT
val = shift_signed( p_buffer[n], m_bps - MPC_FIXED_POINT_SCALE_SHIFT );
val = p_buffer[n] * float_scale;
#else
val = (int)( p_buffer[n] * float_scale );
val = p_buffer[n];
#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;
}
@ -132,7 +126,7 @@ mpc_bool_t CanSeekProc(void *data)
MPC_SAMPLE_FORMAT sampleBuffer[MPC_DECODER_BUFFER_LENGTH];
int framesRead = 0;
int bytesPerFrame = 4; //bitsPerSample == 16, channels == 2
int bytesPerFrame = sizeof(float) * 2; //bitsPerSample == 16, channels == 2
while (framesRead < frames)
{
//Fill from buffer, going by bufferFrames
@ -164,7 +158,7 @@ mpc_bool_t CanSeekProc(void *data)
framesToRead = frames;
}
[self writeToBuffer:((uint16_t*)(buf + (framesRead*bytesPerFrame))) fromBuffer:sampleBuffer frames: bufferFrames];
[self writeToBuffer:((float*)(buf + (framesRead*bytesPerFrame))) fromBuffer:sampleBuffer frames: bufferFrames];
frames -= framesToRead;
framesRead += framesToRead;
@ -209,7 +203,8 @@ mpc_bool_t CanSeekProc(void *data)
[NSNumber numberWithInt:bitrate], @"bitrate",
[NSNumber numberWithFloat:frequency], @"sampleRate",
[NSNumber numberWithDouble:totalFrames], @"totalFrames",
[NSNumber numberWithInt:16], @"bitsPerSample",
[NSNumber numberWithInt:32], @"bitsPerSample",
[NSNumber numberWithBool:YES], @"floatingPoint",
[NSNumber numberWithInt:2], @"channels",
[NSNumber numberWithBool:[source seekable]], @"seekable",
@"host",@"endian",

View File

@ -6,6 +6,8 @@
// Copyright 2013 __NoWork, Inc__. All rights reserved.
//
#import "Plugin.h"
#import "OpusDecoder.h"
@ -97,14 +99,14 @@ opus_int64 sourceTell(void *_stream)
[self didChangeValueForKey:@"properties"];
}
int size = frames * sizeof(int16_t);
int size = frames * channels;
do {
lastSection = currentSection;
numread = op_read_stereo( opusRef, &((int16_t *)buf)[total], size - total);
numread = op_read_float_stereo( opusRef, &((float *)buf)[total], size - total);
currentSection = op_current_link( opusRef );
if (numread > 0) {
total += numread * sizeof(int16_t);
total += numread * channels;
}
if (currentSection != lastSection) {
@ -113,7 +115,7 @@ opus_int64 sourceTell(void *_stream)
} while (total != frames && numread != 0);
return total/sizeof(int16_t);
return total/channels;
}
- (void)close
@ -136,11 +138,13 @@ opus_int64 sourceTell(void *_stream)
{
return [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:channels], @"channels",
[NSNumber numberWithInt:16], @"bitsPerSample",
[NSNumber numberWithInt:32], @"bitsPerSample",
[NSNumber numberWithBool:YES], @"floatingPoint",
[NSNumber numberWithFloat:48000], @"sampleRate",
[NSNumber numberWithDouble:totalFrames], @"totalFrames",
[NSNumber numberWithInt:bitrate], @"bitrate",
[NSNumber numberWithBool:([source seekable] && seekable)], @"seekable",
@"host", @"endian",
nil];
}

View File

@ -91,12 +91,16 @@ long sourceTell(void *datasource)
[self didChangeValueForKey:@"properties"];
}
int size = frames * channels * 2;
do {
lastSection = currentSection;
numread = ov_read(&vorbisRef, &((char *)buf)[total], size - total, 0, 2, 1, &currentSection);
float ** pcm;
numread = ov_read_float(&vorbisRef, &pcm, frames - total, &currentSection);
if (numread > 0) {
for (int i = 0; i < channels; i++) {
for (int j = 0; j < numread; j++) {
((float *)buf)[(total + j) * channels + i] = pcm[i][j];
}
}
total += numread;
}
@ -104,9 +108,9 @@ long sourceTell(void *datasource)
break;
}
} while (total != size && numread != 0);
} while (total != frames && numread != 0);
return total/(channels * 2);
return total;
}
- (void)close
@ -128,11 +132,13 @@ long sourceTell(void *datasource)
{
return [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:channels], @"channels",
[NSNumber numberWithInt:16], @"bitsPerSample",
[NSNumber numberWithInt:32], @"bitsPerSample",
[NSNumber numberWithBool:YES], @"floatingPoint",
[NSNumber numberWithFloat:frequency], @"sampleRate",
[NSNumber numberWithDouble:totalFrames], @"totalFrames",
[NSNumber numberWithInt:bitrate], @"bitrate",
[NSNumber numberWithBool:([source seekable] && seekable)], @"seekable",
@"host", @"endian",
nil];
}

View File

@ -28,6 +28,7 @@
AVCodec *codec;
BOOL seekable;
BOOL floatingPoint;
int bitsPerSample;
int bitrate;
int channels;

View File

@ -129,6 +129,7 @@ int lockmgr_callback(void ** mutex, enum AVLockOp op)
channels = c->channels;
bitrate = ic->bit_rate;
floatingPoint = NO;
switch (c->sample_fmt) {
case AV_SAMPLE_FMT_U8:
case AV_SAMPLE_FMT_U8P:
@ -142,11 +143,19 @@ int lockmgr_callback(void ** mutex, enum AVLockOp op)
case AV_SAMPLE_FMT_S32:
case AV_SAMPLE_FMT_S32P:
bitsPerSample = 32;
break;
case AV_SAMPLE_FMT_FLT:
case AV_SAMPLE_FMT_FLTP:
bitsPerSample = 32;
floatingPoint = YES;
break;
case AV_SAMPLE_FMT_DBL:
case AV_SAMPLE_FMT_DBLP:
bitsPerSample = 32;
bitsPerSample = 64;
floatingPoint = YES;
break;
default:
@ -251,44 +260,6 @@ int lockmgr_callback(void ** mutex, enum AVLockOp op)
numFrames = sampleBufferOffset / bytesPerFrame;
samplePos = 0;
if ( numFrames ) {
switch ( c->sample_fmt ) {
case AV_SAMPLE_FMT_FLT:
case AV_SAMPLE_FMT_FLTP:
{
float * input = (float *) sampleBuffer;
int32_t * output = (int32_t *) sampleBuffer;
for (int i = 0; i < numFrames * channels; ++i)
{
float sample = input[i];
if (sample > 1.0) sample = 1.0;
else if (sample < -1.0) sample = -1.0;
output[i] = sample * INT_MAX;
}
}
break;
case AV_SAMPLE_FMT_DBL:
case AV_SAMPLE_FMT_DBLP:
{
double * input = (double *) sampleBuffer;
int32_t * output = (int32_t *) sampleBuffer;
for (int i = 0; i < numFrames * channels; ++i)
{
double sample = input[i];
if (sample > 1.0) sample = 1.0;
else if (sample < -1.0) sample = -1.0;
output[i] = sample * INT_MAX;
}
}
break;
default: break;
}
}
}
}
@ -311,9 +282,11 @@ int lockmgr_callback(void ** mutex, enum AVLockOp op)
[NSNumber numberWithInt:channels], @"channels",
[NSNumber numberWithInt:bitsPerSample], @"bitsPerSample",
[NSNumber numberWithFloat:frequency], @"sampleRate",
[NSNumber numberWithBool:floatingPoint], @"floatingPoint",
[NSNumber numberWithDouble:totalFrames], @"totalFrames",
[NSNumber numberWithInt:bitrate], @"bitrate",
[NSNumber numberWithBool:([source seekable] && seekable)], @"seekable",
@"host", @"endian",
nil];
}