I'm working off of a custom framework build of the library (4.40) on OS X (I'm not using the tinydecoder). I am able to decode all bit depths of integer files successfully (8, 12, 16, 24, and 32), so I don't think it is an issue with my build.
The code I'm using is fairly straightforward; but no matter what I try float files are decoded to nothing but white noise. I figured I would paste the relevant code excerpt here and see if anyone notices anything that looks funky in the float processing.
I tried swab'ing the buffer, but still got white noise.
It is worth mentioning that the command-line client (wvunpack) produces a silent WAV from the same 32-bit float input file (32bit_float.wv from the test suite).
CODE
- (void) fillPCMBuffer
{
void *writePointer;
int32_t inputBuffer [WP_INPUT_BUFFER_LEN];
uint32_t sample;
for(;;) {
UInt32 bytesToWrite = RING_BUFFER_WRITE_CHUNK_SIZE;
UInt32 bytesAvailableToWrite = [[self pcmBuffer] lengthAvailableToWriteReturningPointer:&writePointer];
UInt32 spaceRequired = WP_INPUT_BUFFER_LEN /* * [self pcmFormat].mChannelsPerFrame */ * (32 / 8);
if(bytesAvailableToWrite < bytesToWrite || spaceRequired > bytesAvailableToWrite) {
break;
}
// Wavpack uses "complete" samples (one sample across all channels), i.e. a Core Audio frame
uint32_t samplesRead = WavpackUnpackSamples(_wpc, inputBuffer, WP_INPUT_BUFFER_LEN / [self pcmFormat].mChannelsPerFrame);
// Handle floating point files
if(MODE_FLOAT & WavpackGetMode(_wpc)) {
if(127 != WavpackGetFloatNormExp(_wpc)) {
NSLog(@"Floating point data not scaled to +/- 1.0");
return;
}
float *inputFloatBuffer = (float *)inputBuffer;
float *floatBuffer = (float *)writePointer;
float audioSample = 0;
for(sample = 0; sample < samplesRead * [self pcmFormat].mChannelsPerFrame; ++sample) {
audioSample = inputFloatBuffer[sample];
*floatBuffer++ = (audioSample < -1.0 ? -1.0 : (audioSample > 1.0 ? 1.0 : audioSample));
}
[[self pcmBuffer] didWriteLength:samplesRead * [self pcmFormat].mChannelsPerFrame * (32 / 8)];
}
else {
float *floatBuffer = (float *)writePointer;
double scaleFactor = (1LL << WavpackGetBitsPerSample(_wpc));
double audioSample = 0;
for(sample = 0; sample < samplesRead * [self pcmFormat].mChannelsPerFrame; ++sample) {
if(0 <= inputBuffer[sample]) {
audioSample = (double)(inputBuffer[sample] / (scaleFactor - 1));
}
else {
audioSample = (double)(inputBuffer[sample] / scaleFactor);
}
*floatBuffer++ = (float)(audioSample < -1.0 ? -1.0 : (audioSample > 1.0 ? 1.0 : audioSample));
}
[[self pcmBuffer] didWriteLength:samplesRead * [self pcmFormat].mChannelsPerFrame * (32 / 8)];
}
// EOS?
if(0 == samplesRead) {
[self setAtEndOfStream:YES];
break;
}
}
}
{
void *writePointer;
int32_t inputBuffer [WP_INPUT_BUFFER_LEN];
uint32_t sample;
for(;;) {
UInt32 bytesToWrite = RING_BUFFER_WRITE_CHUNK_SIZE;
UInt32 bytesAvailableToWrite = [[self pcmBuffer] lengthAvailableToWriteReturningPointer:&writePointer];
UInt32 spaceRequired = WP_INPUT_BUFFER_LEN /* * [self pcmFormat].mChannelsPerFrame */ * (32 / 8);
if(bytesAvailableToWrite < bytesToWrite || spaceRequired > bytesAvailableToWrite) {
break;
}
// Wavpack uses "complete" samples (one sample across all channels), i.e. a Core Audio frame
uint32_t samplesRead = WavpackUnpackSamples(_wpc, inputBuffer, WP_INPUT_BUFFER_LEN / [self pcmFormat].mChannelsPerFrame);
// Handle floating point files
if(MODE_FLOAT & WavpackGetMode(_wpc)) {
if(127 != WavpackGetFloatNormExp(_wpc)) {
NSLog(@"Floating point data not scaled to +/- 1.0");
return;
}
float *inputFloatBuffer = (float *)inputBuffer;
float *floatBuffer = (float *)writePointer;
float audioSample = 0;
for(sample = 0; sample < samplesRead * [self pcmFormat].mChannelsPerFrame; ++sample) {
audioSample = inputFloatBuffer[sample];
*floatBuffer++ = (audioSample < -1.0 ? -1.0 : (audioSample > 1.0 ? 1.0 : audioSample));
}
[[self pcmBuffer] didWriteLength:samplesRead * [self pcmFormat].mChannelsPerFrame * (32 / 8)];
}
else {
float *floatBuffer = (float *)writePointer;
double scaleFactor = (1LL << WavpackGetBitsPerSample(_wpc));
double audioSample = 0;
for(sample = 0; sample < samplesRead * [self pcmFormat].mChannelsPerFrame; ++sample) {
if(0 <= inputBuffer[sample]) {
audioSample = (double)(inputBuffer[sample] / (scaleFactor - 1));
}
else {
audioSample = (double)(inputBuffer[sample] / scaleFactor);
}
*floatBuffer++ = (float)(audioSample < -1.0 ? -1.0 : (audioSample > 1.0 ? 1.0 : audioSample));
}
[[self pcmBuffer] didWriteLength:samplesRead * [self pcmFormat].mChannelsPerFrame * (32 / 8)];
}
// EOS?
if(0 == samplesRead) {
[self setAtEndOfStream:YES];
break;
}
}
}
