[Stk] Using 24bit wav andd aiff files
Carlos Luna
clunaz at hotmail.com
Mon Jun 20 14:06:49 PDT 2011
Hi Gary. From what I´ve found, the first problem is here:
bool FileRead :: getWavInfo( const char *fileName ){......
if ( format_tag == 1 ) { if (temp == 8) dataType_ = STK_SINT8; else if (temp == 16) dataType_ = STK_SINT16; else if (temp == 32) dataType_ = STK_SINT32; }
......}
That part of the code never checks for 24 bits files, so loading such files always returns an error. I changed it to:
.....if ( format_tag == 1 ) { if (temp == 8) dataType_ = STK_SINT8; else if (temp == 16) dataType_ = STK_SINT16; else if (temp == 24) dataType_ = STK_SINT24; else if (temp == 32) dataType_ = STK_SINT32; }.....
Now FileRead loads 24bit files, but won´t reproduce them correctly. The next problem I found is in the read(...) method. You are using bit shifting to get the 3 loaded bytes become the 3 lowest bytes of the buffer, but wouldn´t it also shift the sign bit? Anyway, code is easier to understand so here´s my "fix":
....else if ( dataType_ == STK_SINT24 ) { // 24-bit values are harder to import efficiently since there is // no native 24-bit type. The following routine works but is much // less efficient that that used for the other data types. SINT32 buf; StkFloat gain = 1.0 / 2147483648.0; // 1/ 2^23 * 1/2^8 if ( fseek(fd_, dataOffset_+(offset*3), SEEK_SET ) == -1 ) goto error; for ( i=0; i<nSamples; i++ ) { if ( fread( &buf, 3, 1, fd_ ) != 1 ) goto error; if ( byteswap_ ) swap32( (unsigned char *) &buf ); if (wavFile_) buf <<= 8; if ( doNormalize ) buffer[i] = buf * gain; // "gain" also includes 1/256. See next comment else buffer[i] = buf / 256; // shift to the right without affecting the sign bit? } ....
Notice that I´m shifting bits to the left when the file loaded is a Wav file, and only after byteswapping. That´s because with wav files the 3 loaded bytes always end up being the lowest 3 bytes of the buffer, but the sign bit should be placed in the highest byte. After that, If a normalization is needed, I multiply the buffer by the gain factor, which includes a (1/256), which AFAIK is analogous to a buf >>= 8, without the "sign" problem. If no noemalization is needed, I still apply the buf * 1/256, to get my data back into the lowest 3 bytes without the sign problem.
With all this fixes I finally can get to load and reproduce wav and AIFF files without problem in a Windows XP environment. Now, since I´m quite new to audio file formats, and have only been using c++ for a few months, I could be horribly wrong about all this stuff! What do you think?
Best regards,
Carlos
>
> Hi Carlos,
>
> I recently noticed some discrepancies with 24-bit support in STK (and RtAudio). While SINT24 was listed as "Upper 3 bytes of 32-bit signed integer", the code in FileRead was partly assuming it to be the lower 3 bytes. After some consideration, I decided to change the definition of SINT24 to the "lower 3 bytes" for the next release, with the resulting addition of one line to the FileRead :: open() function code:
>
> if ( fread( &buf, 3, 1, fd_ ) != 1 ) goto error;
> + buf >>= 8;
> if ( byteswap_ ) ...
>
> Is this the problem you found? Do you see any particular advantage to defining an SINT24 to be the upper vs. the lower 3 bytes?
>
> Regards,
>
> --gary
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://ccrma-mail.stanford.edu/pipermail/stk/attachments/20110620/e19f99e3/attachment.html
More information about the Stk
mailing list