summaryrefslogtreecommitdiff
path: root/tools/vag2wav.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/vag2wav.c')
-rwxr-xr-xtools/vag2wav.c202
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 );
+}
+