diff options
Diffstat (limited to 'tools/vag2wav.c')
| -rwxr-xr-x | tools/vag2wav.c | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/tools/vag2wav.c b/tools/vag2wav.c new file mode 100755 index 0000000..09b474a --- /dev/null +++ b/tools/vag2wav.c @@ -0,0 +1,202 @@ +/* + * vag2wav + * + * Converts a PlayStation VAG sound file to a WAV file + * + * Based on VAG-Depack 0.1 by bITmASTER + */ + +#include <stdio.h> +#include <string.h> + +#include "endian.c" + +double f[5][2] = { { 0.0, 0.0 }, + { 60.0 / 64.0, 0.0 }, + { 115.0 / 64.0, -52.0 / 64.0 }, + { 98.0 / 64.0, -55.0 / 64.0 }, + { 122.0 / 64.0, -60.0 / 64.0 } }; + +double samples[28]; + +int main( int argc, char *argv[] ) +{ + FILE *vag, *pcm; + char vag_name[17]; + int predict_nr, shift_factor, flags; + int i; + int d, s; + static double s_1 = 0.0; + static double s_2 = 0.0; + int sz; + unsigned int samp_freq; + unsigned int data_size; + + if(argc < 3) + { + printf("vag2wav - Convert a PlayStation VAG sound file to a WAV file\n"); + printf("usage: vag2wav [vag] [wav file]\n"); + printf("\n"); + printf("This utility is based on PSX VAG-Depack by bITmASTER\n"); + return( -1 ); + } + + vag = fopen( argv[1], "rb" ); + + fread(vag_name, sizeof(char), 4, vag); + + if(vag == NULL) + { + printf("Can't open %s. Aborting.\n", argv[1]); + return -1; + } + + if(strncmp(vag_name, "VAGp", 4)) + { + printf("%s is not in VAG format. Aborting.\n", argv[1]); + return -1; + } + + fseek(vag, 4, SEEK_SET); + i = fgetc(vag) << 24; + i |= fgetc(vag) << 16; + i |= fgetc(vag) << 8; + i |= fgetc(vag); + + printf("Version: %x\n", i); + + fseek(vag, 12, SEEK_SET); + data_size = fgetc(vag) << 24; + data_size |= fgetc(vag) << 16; + data_size |= fgetc(vag) << 8; + data_size |= fgetc(vag); + + printf("Data size: %d bytes\n", data_size); + + fseek(vag, 32, SEEK_SET); + fread(vag_name, sizeof(char), 16, vag); + vag_name[16] = 0; + + printf("Name: %s\n", vag_name); + + fseek(vag, 16, SEEK_SET); + + samp_freq = fgetc(vag)<<24; + samp_freq|=fgetc(vag)<<16; + samp_freq|=fgetc(vag)<<8; + samp_freq|=fgetc(vag); + + printf("Sampling frequency: %d\n", samp_freq); + + fseek( vag, 64, SEEK_SET ); + + /* strcpy( fname, argv[1] ); + p = strrchr( fname, '.' ); + p++; + strcpy( p, "PCM" );*/ + pcm = fopen( argv[2], "wb" ); + + if ( pcm == NULL ) { + printf( "canīt write output file\n" ); + return( -8 ); + } + + +// Write header chunk + fprintf(pcm, "RIFF"); +// Skip file size field for now + fseek(pcm, 4, SEEK_CUR); + + fprintf(pcm, "WAVE"); +// Write fmt chunk + fprintf(pcm, "fmt "); +// Write chunk 1 size in little endian format + fputc(0x10, pcm); + fputc(0, pcm); + fputc(0, pcm); + fputc(0, pcm); +// Write audio format (1 = PCM) + fputc(1, pcm); + fputc(0, pcm); +// Number of channels (1) + fputc(1, pcm); + fputc(0, pcm); +// Write sample rate + fputc((samp_freq & 0xff), pcm); + fputc((samp_freq >> 8) & 0xff, pcm); + fputc(0, pcm); + fputc(0, pcm); +// Write byte rate (SampleRate * NumChannels * BitsPerSample/8) +// That would be 44100*1*(16/8), thus 88200. + fputc(((samp_freq*2) & 0xff), pcm); + fputc(((samp_freq*2) >> 8) & 0xff, pcm); + fputc(((samp_freq*2) >> 16) & 0xff, pcm); + fputc(((samp_freq*2) >> 24) & 0xff, pcm); +// Write block align (NumChannels * BitsPerSample/8), thus 2 + fputc(2, pcm); + fputc(0, pcm); +// Write BitsPerSample + fputc(16, pcm); + fputc(0, pcm); + +// Write data chunk + fprintf(pcm, "data"); + +// Skip SubChunk2Size, we will return to it later + fseek(pcm, 4, SEEK_CUR); + +// Now write data... + + while( ftell(vag) < (data_size+48)) { + predict_nr = fgetc( vag ); + shift_factor = predict_nr & 0xf; + predict_nr >>= 4; + flags = fgetc( vag ); // flags + if ( flags == 7 ) + break; + for ( i = 0; i < 28; i += 2 ) { + d = fgetc( vag ); + s = ( d & 0xf ) << 12; + if ( s & 0x8000 ) + s |= 0xffff0000; + samples[i] = (double) ( s >> shift_factor ); + s = ( d & 0xf0 ) << 8; + if ( s & 0x8000 ) + s |= 0xffff0000; + samples[i+1] = (double) ( s >> shift_factor ); + } + + for ( i = 0; i < 28; i++ ) { + samples[i] = samples[i] + s_1 * f[predict_nr][0] + s_2 * f[predict_nr][1]; + s_2 = s_1; + s_1 = samples[i]; + d = (int) ( samples[i] + 0.5 ); + fputc( d & 0xff, pcm ); + fputc( d >> 8, pcm ); + } + } + +// Get file size + sz = ftell(pcm); + +// Now write ChunkSize + fseek(pcm, 4, SEEK_SET); + + fputc((sz-8) & 0xff, pcm); + fputc(((sz-8)>>8)&0xff, pcm); + fputc(((sz-8)>>16)&0xff,pcm); + fputc(((sz-8)>>24)&0xff,pcm); + +// Now write Subchunk2Size + fseek(pcm, 40, SEEK_SET); + + fputc((sz-44) & 0xff, pcm); + fputc(((sz-44)>>8)&0xff, pcm); + fputc(((sz-44)>>16)&0xff,pcm); + fputc(((sz-44)>>24)&0xff,pcm); + + fclose( pcm ); + fclose( vag ); + return( 0 ); +} + |
