[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