/* * zoom2wav * ZOOM .aud or .zaf to WAV file converter for Zoom PS-02, PS-04, or MRS-8 * * Copyright (C) 2003-2005 Dwight Engen (dengen40@yahoo.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * The deltas table is from aud2wav originally * Copyrighted under the LGPL by Randy Gordon (randy@integrand.com) */ #include #include #include #include #include #define max(a,b) ((a) > (b) ? (a) : (b)) /* Both .aud and .zaf files use 16 bit samples */ #define SAMPLE_BITS 16 static int deltas[] = { 0,1,2,5,9,14,19,0,24,29, 34,40,45,51,57,62,68,75,81,87, 94,100,107,114,120,127,134,141,148,155, 163,170,177,185,192,200,208,215,223,231, 239,246,254,262,271,279,288,297,306,316, 325,336,346,357,368,380,391,404,416,429, 443,457,471,486,501,516,533,549,566,584, 602,621,640,660,681,702,724,747,770,794, 819,845,871,898,926,955,985,1016,1048,1081, 1115,1151,1188,1226,1266,1308,1351,1397,1444,1493, 1544,1598,1653,1712,1773,1836,1903,1972,2045,2121, 2204,2297,2402,2520,2654,2810,2991,3207,3468,3792, 4206,4732,5324,5989,6738,7580,8527,9551,-9551,-8527, -7580,-6738,-5989,-5324,-4732,-4206,-3792,-3468,-3207,-2991, -2810,-2654,-2520,-2402,-2297,-2204,-2121,-2045,-1972,-1903, -1836,-1773,-1712,-1653,-1598,-1544,-1493,-1444,-1397,-1351, -1308,-1266,-1226,-1188,-1151,-1115,-1081,-1048,-1016,-985, -955,-926,-898,-871,-845,-819,-794,-770,-747,-724, -702,-681,-660,-640,-621,-602,-584,-566,-549,-533, -516,-501,-486,-471,-457,-443,-429,-416,-404,-391, -380,-368,-357,-346,-336,-325,-316,-306,-297,-288, -279,-271,-262,-254,-246,-239,-231,-223,-215,-208, -200,-192,-185,-177,-170,-163,-155,-148,-141,-134, -127,-120,-114,-107,-100,-94,-87,-81,-75,-68, -62,-57,-51,-45,-40,-34,-29,-24,0,-19, -14,-9,-5,-2,-1,0 }; uint32_t sample_rate; FILE *in[2]; FILE *out; #define WAVE_FORMAT_PCM 1 typedef struct _DataChunk DataChunk; typedef struct _FmtChunk FmtChunk; typedef struct _WaveHeader WaveHeader; struct _FmtChunk { char chunk_id[4]; /* "fmt " */ uint32_t chunk_size; uint16_t format; uint16_t channels; uint32_t sample_rate; uint32_t avg_bytes_per_second; uint16_t block_align; uint16_t bits_per_sample; }; struct _DataChunk { char chunk_id[4]; /* "data" */ uint32_t chunk_size; }; struct _WaveHeader { char group_id[4]; /* "RIFF" */ uint32_t size; char riff_type[4]; /* "WAVE" */ FmtChunk fmt; }; static void write_wave_header(FILE *out, size_t frames, int channels, int sample_rate, int sample_bits) { WaveHeader header; DataChunk data; uint32_t bytes; bytes = frames * channels * (sample_bits / 8); memset(&header, 0, sizeof(header)); memcpy(header.group_id, "RIFF", 4); memcpy(header.riff_type, "WAVE", 4); header.size = bytes+sizeof(header); memcpy(header.fmt.chunk_id, "fmt ", 4); header.fmt.chunk_size = sizeof(FmtChunk) - 8; header.fmt.format = WAVE_FORMAT_PCM; header.fmt.channels = channels; header.fmt.sample_rate = sample_rate; printf("%d\n",header.fmt.sample_rate); header.fmt.block_align = channels * (sample_bits / 8); header.fmt.avg_bytes_per_second = sample_rate * header.fmt.block_align; header.fmt.bits_per_sample = sample_bits; memcpy(data.chunk_id, "data", 4); data.chunk_size = bytes; fwrite(&header, 1, sizeof(header), out); fwrite(&data, 1, sizeof(data), out); } static int safe_fgetc(FILE *f) { int rc = fgetc(f); if (feof(f)) { printf("ERROR: Unexpected early EOF!\n"); exit(-1); } return rc; } static void audblk2samples(FILE *f, short *sample_buf) { short sample = 0; int bufIndex = 0; int hibyte; int lobyte; int oldsample=0; int i; int deltaIndex; int delta; memset(sample_buf, 0, sizeof(short) * 509); /* Fill smp_buf with 509 samples from AUD data */ /* Read the absolute sample value from the AUD */ lobyte = fgetc(f); if (lobyte == EOF) { static int warn = 0; if (!warn) { warn = 1; printf("WARNING: Reached early EOF padding with zero (aud files not same)"); } return; } hibyte = safe_fgetc(f); /* sample = (short)((hibyte<<8) | (lobyte & 0xff)); * original, gave only noise on intel with xmms player under linux */ sample = (short)((lobyte<<8) | (hibyte & 0xff)); /* * david butcher: and now I hear music! 11 nov 2005 */ sample_buf[bufIndex++] = sample; /* Calculate the next 508 samples from the deltas */ for (i = 0; i < 508; i++) { deltaIndex = safe_fgetc(f); delta = deltas[deltaIndex]; oldsample = sample; sample += delta; /* Check for overflow condition and correct if necessary hacked by Anders Fongen (anders@fongen.no) 8 nov 2005 */ if (oldsample > sample && delta > 0) {sample=32767;} if (oldsample < sample && delta < 0) {sample=-32768;} sample_buf[bufIndex++] = sample; } /* Skip the terminator bytes */ safe_fgetc(f); safe_fgetc(f); } static void auds2wav(int channels, uint32_t length) { uint32_t blocks; uint32_t frames; int i,j,k; blocks = length / 512; frames = blocks * 509; /* Create .wav header */ write_wave_header(out, frames, channels, sample_rate, SAMPLE_BITS); /* david butcher added for info and debugging */ printf("Length: %d\n", length); printf("Blocks: %d\n", blocks); printf("Frames: %d\n", frames); printf("Channels: %d\n", channels); printf("Sample Rate: %d\n", sample_rate); printf("Sample Bits: %d\n", SAMPLE_BITS); printf("Beginning Conversion\n"); /* Process all 512-byte data blocks from the file until EOF found */ for(i = 0; i < blocks; i++) { short samples[2][509]; printf("Complete: %d%%\r", (i * 100) / blocks); /* david butcher set one time prior to entering the loop */ audblk2samples(in[0], &samples[0][0]); /* david butcher making single channel processing more efficient */ if(channels > 1) { for(j = 0; j < channels; j++) audblk2samples(in[j], &samples[j][0]); for(j = 0; j < 509; j++) { for(k = 0; k < channels; k++) { fputc(samples[k][j]&0xff, out); fputc((samples[k][j]>>8)&0xff, out); } } } else { for(j = 0; j < 509; j++) { fputc(samples[0][j]&0xff, out); fputc((samples[0][j]>>8)&0xff, out); } } } printf("\n"); } int main(int argc, char *argv[]) { int i; int input_files = 0; size_t header_size; size_t samples_size = 0; char magic[13]; if (argc < 3 || argc > 4) { puts("Usage: zoom2wav <[.aud|.zaf] file> [[.aud|.zaf] file] "); puts("Example: zoom2wav 00-00.aud leadvocal.wav"); puts("Example: zoom2wav 00-00.aud 00-01.aud stereo.wav"); puts("Example: zoom2wav track0_0.zaf guitarsolo.wav"); puts("Example: zoom2wav track0_0.zaf track0_1.zaf stereo.wav"); return 1; } for(i = 1; i < argc - 1; i++) { if ((in[i-1] = fopen(argv[i], "rb")) == NULL) { printf("Unable to open input file '%s'\n", argv[i]); return 1; } input_files++; } if ((out = fopen(argv[i], "wb")) == NULL) { printf("Unable to open output file '%s'\n", argv[i]); return 1; } /* Sample the first bit to determine if its a .zaf file */ fread(&magic, 1, sizeof(magic), in[0]); if (!strncmp(magic, "ZOOM1D5ZZ3AUD", sizeof(magic))) { /* ZAF file */ sample_rate = 44100; header_size = 16384; printf("Converting in ZAF mode\n"); } else { /* AUD file david butcher If the first byte of the file == 0 the file uses the higher sample rate. */ if(!strncmp(magic, "\000", 1)) { sample_rate = 31250; } else { sample_rate = 15625; } header_size = 512; printf("Converting in AUD mode\n"); } for(i=0; i < input_files; i++) { struct stat sbuf; /* Skip the header */ fseek(in[i], header_size, SEEK_SET); /* Get max length of any input file */ fstat(fileno(in[i]), &sbuf); samples_size = max(samples_size, sbuf.st_size); } /* david butcher added for info and debugging */ printf("Header Size: %d\n", header_size); printf("Samples Size: %d\n", samples_size); auds2wav(input_files, samples_size - header_size); return 0; }