static int read_wav_sample(mame_file *f, struct loaded_sample *sample) { unsigned long offset = 0; UINT32 length, rate, filesize; UINT16 bits, temp16; char buf[32]; #ifndef LSB_FIRST UINT32 sindex; #endif /* read the core header and make sure it's a WAVE file */ offset += mame_fread(f, buf, 4); if (offset < 4) return 0; if (memcmp(&buf[0], "RIFF", 4) != 0) return 0; /* get the total size */ offset += mame_fread(f, &filesize, 4); if (offset < 8) return 0; filesize = intelLong(filesize); /* read the RIFF file type and make sure it's a WAVE file */ offset += mame_fread(f, buf, 4); if (offset < 12) return 0; if (memcmp(&buf[0], "WAVE", 4) != 0) return 0; /* seek until we find a format tag */ while (1) { offset += mame_fread(f, buf, 4); offset += mame_fread(f, &length, 4); length = intelLong(length); if (memcmp(&buf[0], "fmt ", 4) == 0) break; /* seek to the next block */ mame_fseek(f, length, SEEK_CUR); offset += length; if (offset >= filesize) return 0; } /* read the format -- make sure it is PCM */ offset += mame_fread(f, &temp16, 2); temp16 = LITTLE_ENDIANIZE_INT16(temp16); if (temp16 != 1) return 0; /* number of channels -- only mono is supported */ offset += mame_fread(f, &temp16, 2); temp16 = LITTLE_ENDIANIZE_INT16(temp16); if (temp16 != 1) return 0; /* sample rate */ offset += mame_fread(f, &rate, 4); rate = intelLong(rate); /* bytes/second and block alignment are ignored */ offset += mame_fread(f, buf, 6); /* bits/sample */ offset += mame_fread(f, &bits, 2); bits = LITTLE_ENDIANIZE_INT16(bits); if (bits != 8 && bits != 16) return 0; /* seek past any extra data */ mame_fseek(f, length - 16, SEEK_CUR); offset += length - 16; /* seek until we find a data tag */ while (1) { offset += mame_fread(f, buf, 4); offset += mame_fread(f, &length, 4); length = intelLong(length); if (memcmp(&buf[0], "data", 4) == 0) break; /* seek to the next block */ mame_fseek(f, length, SEEK_CUR); offset += length; if (offset >= filesize) return 0; } /* if there was a 0 length data block, we're done */ if (length == 0) return 0; /* fill in the sample data */ sample->length = length; sample->frequency = rate; /* read the data in */ if (bits == 8) { unsigned char *tempptr; int sindex; sample->data = auto_malloc(sizeof(*sample->data) * length); mame_fread(f, sample->data, length); /* convert 8-bit data to signed samples */ tempptr = (unsigned char *)sample->data; for (sindex = length - 1; sindex >= 0; sindex--) sample->data[sindex] = (INT8)(tempptr[sindex] ^ 0x80) * 256; } else { /* 16-bit data is fine as-is */ sample->data = auto_malloc(sizeof(*sample->data) * (length/2)); mame_fread(f, sample->data, length); sample->length /= 2; #ifndef LSB_FIRST for (sindex = 0; sindex < sample->length; sindex++) sample->data[sindex] = LITTLE_ENDIANIZE_INT16(sample->data[sindex]); #endif } return 1; }
static int wave_write(int id) { struct wave_file *w = &wave[id]; UINT32 filesize, offset = 0, temp32; UINT16 temp16; if( !w->file ) return WAVE_ERR; while( w->playpos < w->samples ) { *((INT16 *)w->data + w->playpos) = 0; w->playpos++; } filesize = 4 + /* 'RIFF' */ 4 + /* size of entire file */ 8 + /* 'WAVEfmt ' */ 20 + /* WAVE tag (including size -- 0x10 in dword) */ 4 + /* 'data' */ 4 + /* size of data */ w->length; /* write the core header for a WAVE file */ offset += osd_fwrite(w->file, "RIFF", 4); if( offset < 4 ) { logerror("WAVE write error at offs %d\n", offset); return WAVE_ERR; } temp32 = intelLong(filesize) - 8; offset += osd_fwrite(w->file, &temp32, 4); /* read the RIFF file type and make sure it's a WAVE file */ offset += osd_fwrite(w->file, "WAVE", 4); if( offset < 12 ) { logerror("WAVE write error at offs %d\n", offset); return WAVE_ERR; } /* write a format tag */ offset += osd_fwrite(w->file, "fmt ", 4); if( offset < 12 ) { logerror("WAVE write error at offs %d\n", offset); return WAVE_ERR; } /* size of the following 'fmt ' fields */ offset += osd_fwrite(w->file, "\x10\x00\x00\x00", 4); if( offset < 16 ) { logerror("WAVE write error at offs %d\n", offset); return WAVE_ERR; } /* format: PCM */ temp16 = 1; offset += osd_fwrite_lsbfirst(w->file, &temp16, 2); if( offset < 18 ) { logerror("WAVE write error at offs %d\n", offset); return WAVE_ERR; } /* channels: 1 (mono) */ temp16 = 1; offset += osd_fwrite_lsbfirst(w->file, &temp16, 2); if( offset < 20 ) { logerror("WAVE write error at offs %d\n", offset); return WAVE_ERR; } /* sample rate */ temp32 = intelLong(w->smpfreq); offset += osd_fwrite(w->file, &temp32, 4); if( offset < 24 ) { logerror("WAVE write error at offs %d\n", offset); return WAVE_ERR; } /* byte rate */ temp32 = intelLong(w->smpfreq * w->resolution / 8); offset += osd_fwrite(w->file, &temp32, 4); if( offset < 28 ) { logerror("WAVE write error at offs %d\n", offset); return WAVE_ERR; } /* block align (size of one `sample') */ temp16 = w->resolution / 8; offset += osd_fwrite_lsbfirst(w->file, &temp16, 2); if( offset < 30 ) { logerror("WAVE write error at offs %d\n", offset); return WAVE_ERR; } /* block align */ temp16 = w->resolution; offset += osd_fwrite_lsbfirst(w->file, &temp16, 2); if( offset < 32 ) { logerror("WAVE write error at offs %d\n", offset); return WAVE_ERR; } /* 'data' tag */ offset += osd_fwrite(w->file, "data", 4); if( offset < 36 ) { logerror("WAVE write error at offs %d\n", offset); return WAVE_ERR; } /* data size */ temp32 = intelLong(w->length); offset += osd_fwrite(w->file, &temp32, 4); if( offset < 40 ) { logerror("WAVE write error at offs %d\n", offset); return WAVE_ERR; } if( osd_fwrite_lsbfirst(w->file, w->data, w->length) != w->length ) { logerror("WAVE write error at offs %d\n", offset); return WAVE_ERR; } return WAVE_OK; }
/***************************************************************************** * helper functions *****************************************************************************/ static int wave_read(int id) { struct wave_file *w = &wave[id]; UINT32 offset = 0; UINT32 filesize, temp32; UINT16 channels, bits, temp16; char buf[32]; if( !w->file ) return WAVE_ERR; /* read the core header and make sure it's a WAVE file */ offset += osd_fread(w->file, buf, 4); if( offset < 4 ) { logerror("WAVE read error at offs %d\n", offset); return WAVE_ERR; } if( memcmp (&buf[0], "RIFF", 4) != 0 ) { logerror("WAVE header not 'RIFF'\n"); return WAVE_FMT; } /* get the total size */ offset += osd_fread(w->file, &temp32, 4); if( offset < 8 ) { logerror("WAVE read error at offs %d\n", offset); return WAVE_ERR; } filesize = intelLong(temp32); logerror("WAVE filesize %u bytes\n", filesize); /* read the RIFF file type and make sure it's a WAVE file */ offset += osd_fread(w->file, buf, 4); if( offset < 12 ) { logerror("WAVE read error at offs %d\n", offset); return WAVE_ERR; } if( memcmp (&buf[0], "WAVE", 4) != 0 ) { logerror("WAVE RIFF type not 'WAVE'\n"); return WAVE_FMT; } /* seek until we find a format tag */ while( 1 ) { offset += osd_fread(w->file, buf, 4); offset += osd_fread(w->file, &temp32, 4); w->length = intelLong(temp32); if( memcmp(&buf[0], "fmt ", 4) == 0 ) break; /* seek to the next block */ osd_fseek(w->file, w->length, SEEK_CUR); offset += w->length; if( offset >= filesize ) { logerror("WAVE no 'fmt ' tag found\n"); return WAVE_ERR; } } /* read the format -- make sure it is PCM */ offset += osd_fread_lsbfirst(w->file, &temp16, 2); if( temp16 != 1 ) { logerror("WAVE format %d not supported (not = 1 PCM)\n", temp16); return WAVE_ERR; } logerror("WAVE format %d (PCM)\n", temp16); /* number of channels -- only mono is supported */ offset += osd_fread_lsbfirst(w->file, &channels, 2); if( channels != 1 && channels != 2 ) { logerror("WAVE channels %d not supported (only 1 mono or 2 stereo)\n", channels); return WAVE_ERR; } logerror("WAVE channels %d\n", channels); /* sample rate */ offset += osd_fread(w->file, &temp32, 4); w->smpfreq = intelLong(temp32); logerror("WAVE sample rate %d Hz\n", w->smpfreq); /* bytes/second and block alignment are ignored */ offset += osd_fread(w->file, buf, 6); /* bits/sample */ offset += osd_fread_lsbfirst(w->file, &bits, 2); if( bits != 8 && bits != 16 ) { logerror("WAVE %d bits/sample not supported (only 8/16)\n", bits); return WAVE_ERR; } logerror("WAVE bits/sample %d\n", bits); w->resolution = bits; /* seek past any extra data */ osd_fseek(w->file, w->length - 16, SEEK_CUR); offset += w->length - 16; /* seek until we find a data tag */ while( 1 ) { offset += osd_fread(w->file, buf, 4); offset += osd_fread(w->file, &temp32, 4); w->length = intelLong(temp32); if( memcmp(&buf[0], "data", 4) == 0 ) break; /* seek to the next block */ osd_fseek(w->file, w->length, SEEK_CUR); offset += w->length; if( offset >= filesize ) { logerror("WAVE not 'data' tag found\n"); return WAVE_ERR; } } /* allocate the game sample */ w->data = malloc(w->length); if( w->data == NULL ) { logerror("WAVE failed to malloc %d bytes\n", w->length); return WAVE_ERR; } /* read the data in */ if( w->resolution == 8 ) { if( osd_fread(w->file, w->data, w->length) != w->length ) { logerror("WAVE failed read %d data bytes\n", w->length); free(w->data); return WAVE_ERR; } if( channels == 2 ) { UINT8 *src = w->data; INT8 *dst = w->data; logerror("WAVE mixing 8-bit unsigned stereo to 8-bit signed mono\n"); /* convert stereo 8-bit data to mono signed samples */ for( temp32 = 0; temp32 < w->length/2; temp32++ ) { *dst = ((src[0] + src[1]) / 2) ^ 0x80; dst += 1; src += 2; } w->length /= 2; w->data = realloc(w->data, w->length); if( w->data == NULL ) { logerror("WAVE failed to malloc %d bytes\n", w->length); return WAVE_ERR; } } else { UINT8 *src = w->data; INT8 *dst = w->data; logerror("WAVE converting 8-bit unsigned to 8-bit signed\n"); /* convert 8-bit data to signed samples */ for( temp32 = 0; temp32 < w->length; temp32++ ) *dst++ = *src++ ^ 0x80; } } else { /* 16-bit data is fine as-is */ if( osd_fread_lsbfirst(w->file, w->data, w->length) != w->length ) { logerror("WAVE failed read %d data bytes\n", w->length); free(w->data); return WAVE_ERR; } if( channels == 2 ) { INT16 *src = w->data; INT16 *dst = w->data; logerror("WAVE mixing 16-bit stereo to 16-bit mono\n"); /* convert stereo 16-bit data to mono */ for( temp32 = 0; temp32 < w->length/2; temp32++ ) { *dst = ((INT32)src[0] + (INT32)src[1]) / 2; dst += 1; src += 2; } w->length /= 2; w->data = realloc(w->data, w->length); if( w->data == NULL ) { logerror("WAVE failed to malloc %d bytes\n", w->length); return WAVE_ERR; } } else { logerror("WAVE using 16-bit signed samples as is\n"); } } w->samples = w->length * 8 / w->resolution; logerror("WAVE %d samples - %d:%02d\n", w->samples, (w->samples/w->smpfreq)/60, (w->samples/w->smpfreq)%60); return WAVE_OK; }
static struct GameSample *read_wav_sample(void *f) { unsigned long offset = 0; UINT32 length, rate, filesize, temp32; UINT16 bits, temp16; char buf[32]; struct GameSample *result; /* read the core header and make sure it's a WAVE file */ offset += osd_fread(f, buf, 4); if (offset < 4) return NULL; if (memcmp(&buf[0], "RIFF", 4) != 0) return NULL; /* get the total size */ offset += osd_fread(f, &filesize, 4); if (offset < 8) return NULL; filesize = intelLong(filesize); /* read the RIFF file type and make sure it's a WAVE file */ offset += osd_fread(f, buf, 4); if (offset < 12) return NULL; if (memcmp(&buf[0], "WAVE", 4) != 0) return NULL; /* seek until we find a format tag */ while (1) { offset += osd_fread(f, buf, 4); offset += osd_fread(f, &length, 4); length = intelLong(length); if (memcmp(&buf[0], "fmt ", 4) == 0) break; /* seek to the next block */ osd_fseek(f, length, SEEK_CUR); offset += length; if (offset >= filesize) return NULL; } /* read the format -- make sure it is PCM */ offset += osd_fread_lsbfirst(f, &temp16, 2); if (temp16 != 1) return NULL; /* number of channels -- only mono is supported */ offset += osd_fread_lsbfirst(f, &temp16, 2); if (temp16 != 1) return NULL; /* sample rate */ offset += osd_fread(f, &rate, 4); rate = intelLong(rate); /* bytes/second and block alignment are ignored */ offset += osd_fread(f, buf, 6); /* bits/sample */ offset += osd_fread_lsbfirst(f, &bits, 2); if (bits != 8 && bits != 16) return NULL; /* seek past any extra data */ osd_fseek(f, length - 16, SEEK_CUR); offset += length - 16; /* seek until we find a data tag */ while (1) { offset += osd_fread(f, buf, 4); offset += osd_fread(f, &length, 4); length = intelLong(length); if (memcmp(&buf[0], "data", 4) == 0) break; /* seek to the next block */ osd_fseek(f, length, SEEK_CUR); offset += length; if (offset >= filesize) return NULL; } /* allocate the game sample */ result = malloc(sizeof(struct GameSample) + length); if (result == NULL) return NULL; /* fill in the sample data */ result->length = length; result->smpfreq = rate; result->resolution = bits; /* read the data in */ if (bits == 8) { osd_fread(f, result->data, length); /* convert 8-bit data to signed samples */ for (temp32 = 0; temp32 < length; temp32++) result->data[temp32] ^= 0x80; } else { /* 16-bit data is fine as-is */ osd_fread_lsbfirst(f, result->data, length); } return result; }