static casserr_t wavfile_process(cassette_image *cassette, struct CassetteOptions *opts, int read_waveform) { UINT8 file_header[12]; UINT8 tag_header[8]; UINT8 format_tag[16]; UINT32 stated_size; UINT64 file_size; UINT32 tag_size; UINT32 tag_samples; UINT64 offset; int format_specified = FALSE; UINT16 format_type = 0; UINT32 bytes_per_second = 0; // UINT16 block_align = 0; int waveform_flags = 0; /* read header */ cassette_image_read(cassette, file_header, 0, sizeof(file_header)); offset = sizeof(file_header); /* check magic numbers */ if (memcmp(&file_header[0], magic1, 4)) return CASSETTE_ERROR_INVALIDIMAGE; if (memcmp(&file_header[8], magic2, 4)) return CASSETTE_ERROR_INVALIDIMAGE; /* read and sanity check size */ stated_size = get_leuint32(&file_header[4]) + 8; file_size = cassette_image_size(cassette); if (stated_size > file_size) stated_size = (UINT32) file_size; while(offset < stated_size) { cassette_image_read(cassette, tag_header, offset, sizeof(tag_header)); tag_size = get_leuint32(&tag_header[4]); offset += sizeof(tag_header); if (!memcmp(tag_header, format_tag_id, 4)) { /* format tag */ if (format_specified || (tag_size < sizeof(format_tag))) return CASSETTE_ERROR_INVALIDIMAGE; format_specified = TRUE; cassette_image_read(cassette, format_tag, offset, sizeof(format_tag)); format_type = get_leuint16(&format_tag[0]); opts->channels = get_leuint16(&format_tag[2]); opts->sample_frequency = get_leuint32(&format_tag[4]); bytes_per_second = get_leuint32(&format_tag[8]); // block_align = get_leuint16(&format_tag[12]); opts->bits_per_sample = get_leuint16(&format_tag[14]); if (format_type != WAV_FORMAT_PCM) return CASSETTE_ERROR_INVALIDIMAGE; if (opts->sample_frequency * opts->bits_per_sample * opts->channels / 8 != bytes_per_second) return CASSETTE_ERROR_INVALIDIMAGE; switch(opts->bits_per_sample) { case 8: waveform_flags = CASSETTE_WAVEFORM_8BIT | CASSETTE_WAVEFORM_UNSIGNED; // 8-bits wav are stored unsigned break; case 16: waveform_flags = CASSETTE_WAVEFORM_16BITLE; break; case 32: waveform_flags = CASSETTE_WAVEFORM_32BITLE; break; default: return CASSETTE_ERROR_INVALIDIMAGE; } } else if (!memcmp(tag_header, data_tag_id, 4)) { /* data tag */ if (!format_specified) return CASSETTE_ERROR_INVALIDIMAGE; if (read_waveform) { tag_samples = tag_size / (opts->bits_per_sample / 8) / opts->channels; cassette_read_samples(cassette, opts->channels, 0.0, tag_samples / ((double) opts->sample_frequency), tag_samples, offset, waveform_flags); } } else { /* ignore other tags */ } offset += tag_size; } return CASSETTE_ERROR_SUCCESS; }
static int csw_cas_to_wav_size( const uint8_t *casdata, int caslen ) { uint32_t SampleRate; uint32_t NumberOfPulses; uint8_t MajorRevision; uint8_t MinorRevision; uint8_t CompressionType; uint8_t Flags; uint8_t HeaderExtensionLength; std::vector<uint8_t> gz_ptr; int total_size; z_stream d_stream; int err; uint8_t *in_ptr; int bsize=0; if ( memcmp( casdata, CSW_HEADER, sizeof(CSW_HEADER)-1 ) ) { LOG_FORMATS( "csw_cas_to_wav_size: cassette image has incompatible header\n" ); goto cleanup; } if (casdata[0x16]!=0x1a) { LOG_FORMATS( "csw_cas_to_wav_size: Terminator Code Not Found\n" ); goto cleanup; } MajorRevision=casdata[0x17]; MinorRevision=casdata[0x18]; LOG_FORMATS("Version %d : %d\n",MajorRevision,MinorRevision); if (casdata[0x17]!=2) { LOG_FORMATS( "csw_cas_to_wav_size: Unsuported Major Version\n" ); goto cleanup; } SampleRate=get_leuint32(casdata+0x19); LOG_FORMATS("Sample rate %u\n",SampleRate); NumberOfPulses=get_leuint32(casdata+0x1d); LOG_FORMATS("Number Of Pulses %u\n",NumberOfPulses); CompressionType=casdata[0x21]; Flags=casdata[0x22]; HeaderExtensionLength=casdata[0x23]; LOG_FORMATS("CompressionType %u Flast %u HeaderExtensionLength %u\n",CompressionType,Flags,HeaderExtensionLength); mycaslen=caslen; //from here on down for now I am assuming it is compressed csw file. in_ptr = (uint8_t*) casdata+0x34+HeaderExtensionLength; gz_ptr.resize( 8 ); d_stream.next_in = (unsigned char *)in_ptr; d_stream.avail_in = caslen - ( in_ptr - casdata ); d_stream.total_in=0; d_stream.next_out = &gz_ptr[0]; d_stream.avail_out = 1; d_stream.total_out=0; d_stream.zalloc = nullptr; d_stream.zfree = nullptr; d_stream.opaque = nullptr; d_stream.data_type=0; err = inflateInit( &d_stream ); if ( err != Z_OK ) { LOG_FORMATS( "inflateInit2 error: %d\n", err ); goto cleanup; } total_size=1; do { d_stream.next_out = &gz_ptr[0]; d_stream.avail_out=1; err=inflate( &d_stream, Z_SYNC_FLUSH ); if (err==Z_OK) { bsize=gz_ptr[0]; if (bsize==0) { d_stream.avail_out=4; d_stream.next_out = &gz_ptr[0]; err=inflate( &d_stream, Z_SYNC_FLUSH ); bsize=get_leuint32(&gz_ptr[0]); } total_size=total_size+bsize; } } while (err==Z_OK); if ( err != Z_STREAM_END ) { LOG_FORMATS( "inflate error: %d\n", err ); goto cleanup; } err = inflateEnd( &d_stream ); if ( err != Z_OK ) { LOG_FORMATS( "inflateEnd error: %d\n", err ); goto cleanup; } return total_size; cleanup: return -1; }
static int csw_cas_fill_wave( INT16 *buffer, int length, UINT8 *bytes ) { UINT32 SampleRate; UINT32 NumberOfPulses; UINT8 CompressionType; UINT8 Flags; UINT8 HeaderExtensionLength; INT8 Bit; UINT8 *gz_ptr = NULL; int total_size; z_stream d_stream; int err; UINT8 *in_ptr; int bsize=0; int i; LOG_FORMATS("Length %d\n",length); SampleRate=get_leuint32(bytes+0x19); LOG_FORMATS("Sample rate %d\n",SampleRate); NumberOfPulses=get_leuint32(bytes+0x1d); LOG_FORMATS("Number Of Pulses %d\n",NumberOfPulses); CompressionType=bytes[0x21]; Flags=bytes[0x22]; HeaderExtensionLength=bytes[0x23]; if ((Flags&0)==0) { Bit=-100; } else { Bit=100; } LOG_FORMATS("CompressionType %d Flast %d HeaderExtensionLength %d\n",CompressionType,Flags,HeaderExtensionLength); //from here on down for now I am assuming it is compressed csw file. in_ptr = (UINT8*) bytes+0x34+HeaderExtensionLength; gz_ptr = (UINT8*)malloc( 8 ); d_stream.next_in = (unsigned char *)in_ptr; d_stream.avail_in = mycaslen - ( in_ptr - bytes ); d_stream.total_in=0; d_stream.next_out = gz_ptr; d_stream.avail_out = 1; d_stream.total_out=0; d_stream.zalloc = 0; d_stream.zfree = 0; d_stream.opaque = 0; d_stream.data_type=0; err = inflateInit( &d_stream ); if ( err != Z_OK ) { LOG_FORMATS( "inflateInit2 error: %d\n", err ); goto cleanup; } total_size=0; do { d_stream.next_out = gz_ptr; d_stream.avail_out=1; err=inflate( &d_stream, Z_SYNC_FLUSH ); if (err==Z_OK) { bsize=gz_ptr[0]; if (bsize==0) { d_stream.avail_out=4; d_stream.next_out = gz_ptr; err=inflate( &d_stream, Z_SYNC_FLUSH ); bsize=get_leuint32(gz_ptr); } for (i=0;i<bsize;i++) { buffer[total_size++]=Bit; } Bit=-Bit; } } while (err==Z_OK); if ( err != Z_STREAM_END ) { LOG_FORMATS( "inflate error: %d\n", err ); goto cleanup; } err = inflateEnd( &d_stream ); if ( err != Z_OK ) { LOG_FORMATS( "inflateEnd error: %d\n", err ); goto cleanup; } if ( gz_ptr ) { free( gz_ptr ); gz_ptr = NULL; } return length; cleanup: if ( gz_ptr ) { free( gz_ptr ); gz_ptr = NULL; } return -1; }
static int csw_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes ) { uint32_t SampleRate; uint32_t NumberOfPulses; uint8_t CompressionType; uint8_t Flags; uint8_t HeaderExtensionLength; int8_t Bit; std::vector<uint8_t> gz_ptr; int total_size; z_stream d_stream; int err; uint8_t *in_ptr; int bsize=0; int i; LOG_FORMATS("Length %d\n",length); SampleRate=get_leuint32(bytes+0x19); LOG_FORMATS("Sample rate %u\n",SampleRate); NumberOfPulses=get_leuint32(bytes+0x1d); LOG_FORMATS("Number Of Pulses %u\n",NumberOfPulses); CompressionType=bytes[0x21]; Flags=bytes[0x22]; HeaderExtensionLength=bytes[0x23]; if ((Flags&0)==0) { Bit=-100; } else { Bit=100; } LOG_FORMATS("CompressionType %u Flast %u HeaderExtensionLength %u\n",CompressionType,Flags,HeaderExtensionLength); //from here on down for now I am assuming it is compressed csw file. in_ptr = (uint8_t*) bytes+0x34+HeaderExtensionLength; gz_ptr.resize( 8 ); d_stream.next_in = (unsigned char *)in_ptr; d_stream.avail_in = mycaslen - ( in_ptr - bytes ); d_stream.total_in=0; d_stream.next_out = &gz_ptr[0]; d_stream.avail_out = 1; d_stream.total_out=0; d_stream.zalloc = nullptr; d_stream.zfree = nullptr; d_stream.opaque = nullptr; d_stream.data_type=0; err = inflateInit( &d_stream ); if ( err != Z_OK ) { LOG_FORMATS( "inflateInit2 error: %d\n", err ); goto cleanup; } total_size=0; do { d_stream.next_out = &gz_ptr[0]; d_stream.avail_out=1; err=inflate( &d_stream, Z_SYNC_FLUSH ); if (err==Z_OK) { bsize=gz_ptr[0]; if (bsize==0) { d_stream.avail_out=4; d_stream.next_out = &gz_ptr[0]; err=inflate( &d_stream, Z_SYNC_FLUSH ); bsize=get_leuint32(&gz_ptr[0]); } for (i=0;i<bsize;i++) { buffer[total_size++]=Bit; } Bit=-Bit; } } while (err==Z_OK); if ( err != Z_STREAM_END ) { LOG_FORMATS( "inflate error: %d\n", err ); goto cleanup; } err = inflateEnd( &d_stream ); if ( err != Z_OK ) { LOG_FORMATS( "inflateEnd error: %d\n", err ); goto cleanup; } return length; cleanup: return -1; }
static int csw_cas_to_wav_size( const UINT8 *casdata, int caslen ) { UINT32 SampleRate; UINT32 NumberOfPulses; UINT8 MajorRevision; UINT8 MinorRevision; UINT8 CompressionType; UINT8 Flags; UINT8 HeaderExtensionLength; UINT8 *gz_ptr = NULL; int total_size; z_stream d_stream; int err; UINT8 *in_ptr; int bsize=0; if ( memcmp( casdata, CSW_HEADER, sizeof(CSW_HEADER) ) ) { logerror( "csw_cas_to_wav_size: cassette image has incompatible header\n" ); goto cleanup; } if (casdata[0x16]!=0x1a) { logerror( "csw_cas_to_wav_size: Terminator Code Not Found\n" ); goto cleanup; } MajorRevision=casdata[0x17]; MinorRevision=casdata[0x18]; logerror("Version %d : %d\n",MajorRevision,MinorRevision); if (casdata[0x17]!=2){ logerror( "csw_cas_to_wav_size: Unsuported Major Version\n" ); goto cleanup; } SampleRate=get_leuint32(casdata+0x19); logerror("Sample rate %d\n",SampleRate); NumberOfPulses=get_leuint32(casdata+0x1d); logerror("Number Of Pulses %d\n",NumberOfPulses); CompressionType=casdata[0x21]; Flags=casdata[0x22]; HeaderExtensionLength=casdata[0x23]; logerror("CompressionType %d Flast %d HeaderExtensionLength %d\n",CompressionType,Flags,HeaderExtensionLength); mycaslen=caslen; //from here on down for now I am assuming it is compressed csw file. in_ptr = (UINT8*) casdata+0x34+HeaderExtensionLength; gz_ptr = (UINT8*)malloc( 8 ); d_stream.next_in = (unsigned char *)in_ptr; d_stream.avail_in = caslen - ( in_ptr - casdata ); d_stream.total_in=0; d_stream.next_out = gz_ptr; d_stream.avail_out = 1; d_stream.total_out=0; d_stream.zalloc = 0; d_stream.zfree = 0; d_stream.opaque = 0; d_stream.data_type=0; err = inflateInit( &d_stream ); if ( err != Z_OK ) { logerror( "inflateInit2 error: %d\n", err ); goto cleanup; } total_size=1; do { d_stream.next_out = gz_ptr; d_stream.avail_out=1; err=inflate( &d_stream, Z_SYNC_FLUSH ); if (err==Z_OK) { bsize=gz_ptr[0]; if (bsize==0) { d_stream.avail_out=4; d_stream.next_out = gz_ptr; err=inflate( &d_stream, Z_SYNC_FLUSH ); bsize=get_leuint32(gz_ptr); } total_size=total_size+bsize; } } while (err==Z_OK); if ( err != Z_STREAM_END ) { logerror( "inflate error: %d\n", err ); goto cleanup; } err = inflateEnd( &d_stream ); if ( err != Z_OK ) { logerror( "inflateEnd error: %d\n", err ); goto cleanup; } if ( gz_ptr ) { free( gz_ptr ); gz_ptr = NULL; } return total_size; cleanup: if ( gz_ptr ) { free( gz_ptr ); gz_ptr = NULL; } return -1; }