From ce6c31f0ee258d163dbc62553d2f0d9400a568b2 Mon Sep 17 00:00:00 2001 From: kramm Date: Mon, 18 Mar 2002 10:37:32 +0000 Subject: [PATCH] initial revision --- src/wav.c | 242 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/wav.h | 26 +++++++ src/wav2swf.c | 146 ++++++++++++++++++++++++++++++++++ 3 files changed, 414 insertions(+) create mode 100644 src/wav.c create mode 100644 src/wav.h create mode 100644 src/wav2swf.c diff --git a/src/wav.c b/src/wav.c new file mode 100644 index 0000000..e12e739 --- /dev/null +++ b/src/wav.c @@ -0,0 +1,242 @@ +/* wav.c + Routines for handling .wav files + + Part of the swftools package. + + Copyright (c) 2001 Matthias Kramm + + This file is distributed under the GPL, see file COPYING for details */ + +#include +#include +#include "wav.h" + +struct WAVBlock { + char id[4]; + unsigned int size; +}; + +int getWAVBlock(FILE*fi, struct WAVBlock*block) +{ + unsigned int size; + unsigned char b[4]; + if(fread(block->id,1,4,fi)<4) + return 0; + if(fread(b,1,4,fi)<4) + return 0; + block->size = b[0]|b[1]<<8|b[2]<<16|b[3]<<24; + printf("Chunk: [%c%c%c%c] (%d bytes)\n", + block->id[0],block->id[1], + block->id[2],block->id[3], + block->size); + return 1; +} + +int readWAV(char* filename, struct WAV*wav) +{ + FILE*fi = fopen(filename, "rb"); + unsigned char b[16]; + long int filesize; + struct WAVBlock block; + long int pos; + if(!fi) + return 0; + fseek(fi, 0, SEEK_END); + filesize = ftell(fi); + fseek(fi, 0, SEEK_SET); + + printf("Filesize: %d\n", filesize); + + if(!getWAVBlock (fi, &block)) + return 0; + if(strncmp(block.id,"RIFF",4)) { + fprintf(stderr, "readWAV: not a wav file\n"); + return 0; + } + if(block.size + 8 < filesize) + fprintf(stderr, "readWAV: warning - more tags (%d extra bytes)\n", + filesize - block.size - 8); + if(block.size + 8 > filesize) + fprintf(stderr, "readWAV: warning - short file (%d bytes missing)\n", + block.size + 8 - filesize); + if(fread(b, 1, 4, fi) < 4) { + return 0; + } + if(strncmp(b, "WAVE", 4)) { + fprintf(stderr, "readWAV: not a WAV file (2)\n"); + return 0; + } + + do + { + getWAVBlock(fi, &block); + pos = ftell(fi); + if(!strncmp(block.id, "fmt ", 4)) { + if(fread(&b, 1, 16, fi)<16) + return 0; + wav->tag = b[0]|b[1]<<8; + wav->channels = b[2]|b[3]<<8; + wav->sampsPerSec = b[4]|b[5]<<8|b[6]<<16|b[7]<<24; + wav->bytesPerSec = b[8]|b[9]<<8|b[10]<<16|b[11]<<24; + wav->align = b[12]|b[13]<<8; + wav->bps = b[14]|b[15]<<8; + } else if (!strncmp(block.id, "LIST", 4)) { + // subchunk ICMT (comment) may exist + } else if (!strncmp(block.id, "data", 4)) { + wav->data = malloc(block.size); + if(!wav->data) { + fprintf(stderr, "Out of memory (%d bytes needed)", block.size); + return 0; + } + if(fread(wav->data, 1, block.size, fi) < block.size) + return 0; + wav->size = block.size; + } + pos+=block.size; + fseek(fi, pos, SEEK_SET); + } + while (pos < filesize); + + return 1; +} + +int writeWAV(char*filename, struct WAV*wav) +{ + FILE*fi = fopen(filename, "wb"); + char*b="RIFFWAVEfmt \x10\0\0\0data"; + char c[16]; + unsigned long int w32; + if(!fi) + return 0; + fwrite(b, 4, 1, fi); + w32=(/*fmt*/8+0x10+/*data*/8+wav->size); + c[0] = w32; + c[1] = w32>>8; + c[2] = w32>>16; + c[3] = w32>>24; + fwrite(c, 4, 1, fi); + fwrite(&b[4], 12, 1, fi); + c[0] = wav->tag; + c[1] = wav->tag>>8; + c[2] = wav->channels; + c[3] = wav->channels>>8; + c[4] = wav->sampsPerSec; + c[5] = wav->sampsPerSec>>8; + c[6] = wav->sampsPerSec>>16; + c[7] = wav->sampsPerSec>>24; + c[8] = wav->bytesPerSec; + c[9] = wav->bytesPerSec>>8; + c[10] = wav->bytesPerSec>>16; + c[11] = wav->bytesPerSec>>24; + c[12] = wav->align; + c[13] = wav->align>>8; + c[14] = wav->bps; + c[15] = wav->bps>>8; + fwrite(c, 16, 1, fi); + fwrite(&b[16], 4, 1, fi); + c[0] = wav->size; + c[1] = wav->size>>8; + c[2] = wav->size>>16; + c[3] = wav->size>>24; + fwrite(c,4,1,fi); + printf("writing %d converted bytes\n", wav->size); + fwrite(wav->data,wav->size,1,fi); + fclose(fi); + return 1; +} + +void printWAVInfo(struct WAV*wav) +{ + printf("tag:%04x channels:%d samples/sec:%d bytes/sec:%d align:%d bits/sample:%d size:%d\n", + wav->tag, wav->channels, wav->sampsPerSec, wav->bytesPerSec, + wav->align, wav->bps, wav->size); +} + +int convertWAV2mono(struct WAV*src, struct WAV*dest, int rate) +{ + int samplelen=src->size/src->align; + int bps=src->bps; + double ratio; + double pos = 0; + int pos2 = 0; + int channels=src->channels; + int i; + int fill; + + dest->sampsPerSec = rate; + dest->bps = 16; + dest->channels = 1; + dest->align = 2; + dest->tag = src->tag; + dest->bytesPerSec = dest->sampsPerSec*dest->align; + + ratio = (double)dest->sampsPerSec/(double)src->sampsPerSec; + fill = (int)(ratio+1)*2; + + dest->data = (unsigned char*)malloc((int)(samplelen*ratio*2)+128); + if(!dest->data) + return 0; + dest->size = (int)(samplelen*ratio)*2; + + if(bps == 8) { + if(ratio <= 1) { + for(i=0; isize; i+=channels) { + int pos2 = ((int)pos)*2; + dest->data[pos2] = 0; + dest->data[pos2+1] = src->data[i]+128; + pos += ratio; + } + } else { + for(i=0; isize; i+=channels) { + int j; + int pos2 = ((int)pos)*2; + for(j=0;jdata[pos2+j+0] = 0; + dest->data[pos2+j+1] = src->data[i]+128; + } + pos += ratio; + } + } + } else if(bps == 16) { + if(ratio <= 1) { + for(i=0; isize/2; i+=channels) { + int pos2 = ((int)pos)*2; + dest->data[pos2+0]=src->data[i*2]; + dest->data[pos2+1]=src->data[i*2+1]; + pos += ratio; + } + } else { + for(i=0; isize/2; i+=channels) { + int j; + int pos2 = ((int)pos)*2; + for(j=0;jdata[pos2+j+0] = src->data[i*2]; + dest->data[pos2+j+1] = src->data[i*2+1]; + } + pos += ratio; + } + } + } else if(bps == 32) { + if(ratio <= 1) { + for(i=0; isize/4; i+=channels) { + int pos2 = ((int)pos)*2; + dest->data[pos2+0]=src->data[i*4+2]; + dest->data[pos2+1]=src->data[i*4+3]; + pos += ratio; + } + } else { + for(i=0; isize/4; i+=channels) { + int j; + int pos2 = ((int)pos)*2; + for(j=0;jdata[pos2+j+0] = src->data[i*4+2]; + dest->data[pos2+j+1] = src->data[i*4+3]; + } + pos += ratio; + } + } + } + return 1; +} + + diff --git a/src/wav.h b/src/wav.h new file mode 100644 index 0000000..c671df8 --- /dev/null +++ b/src/wav.h @@ -0,0 +1,26 @@ +/* wav.h + Header file for wav.c + + Part of the swftools package. + + Copyright (c) 2001 Matthias Kramm + + This file is distributed under the GPL, see file COPYING for details */ + +struct WAV { + unsigned short tag; + unsigned short channels; + unsigned long sampsPerSec; + unsigned long bytesPerSec; + unsigned short align; + unsigned short bps; + + unsigned char*data; + unsigned int size; +}; + +int readWAV(char* filename, struct WAV*wav); +int writeWAV(char*filename, struct WAV*wav); +void printWAVInfo(struct WAV*wav); +int convertWAV2mono(struct WAV*src, struct WAV*dest, int rate); + diff --git a/src/wav2swf.c b/src/wav2swf.c new file mode 100644 index 0000000..6bf2ec7 --- /dev/null +++ b/src/wav2swf.c @@ -0,0 +1,146 @@ +/* swfextract.c + Allows to extract parts of the swf into a new file. + + Part of the swftools package. + + Copyright (c) 2001 Matthias Kramm + + This file is distributed under the GPL, see file COPYING for details */ + +#include +#include +#include "../lib/rfxswf.h" +#include "../lib/args.h" +#include "wav.h" + +char * filename = 0; +char * outputname = "output.swf"; +int verbose = 2; + +struct options_t options[] = +{ + {"o","output"}, + {"v","verbose"}, + {"V","version"}, + {0,0} +}; + +int args_callback_option(char*name,char*val) +{ + if(!strcmp(name, "V")) { + printf("wav2swf - part of %s %s\n", PACKAGE, VERSION); + exit(0); + } + else if(!strcmp(name, "o")) { + outputname = val; + return 1; + } + else if(!strcmp(name, "v")) { + verbose ++; + return 0; + } + else { + printf("Unknown option: -%s\n", name); + exit(1); + } + return 0; +} +int args_callback_longoption(char*name,char*val) +{ + return args_long2shortoption(options, name, val); +} +void args_callback_usage(char*name) +{ + printf("Usage: %s [-o filename] file.wav\n", name); + printf("\t-v , --verbose\t\t\t Be more verbose\n"); + printf("\t-o , --output filename\t\t set output filename (default: output.swf)\n"); + printf("\t-V , --version\t\t Print program version and exit\n"); +} +int args_callback_command(char*name,char*val) +{ + if(filename) { + fprintf(stderr, "Only one file allowed. You supplied at least two. (%s and %s)\n", + filename, name); + } + filename = name; + return 0; +} + +int main (int argc,char ** argv) +{ SWF swf; + RGBA rgb; + SRECT r; + S32 width=300,height = 300; + TAG * tag; + + int f,i,ls1,fs1; + int count; + int t; + struct WAV wav,wav2; + int blocksize = 1152; + U16* samples; + int numsamples; + + processargs(argc, argv); + initLog(0,-1,0,0,-1,verbose); + + if(!readWAV(filename, &wav)) + { + logf(" Error reading %s", filename); + exit(1); + } + convertWAV2mono(&wav,&wav2, 44100); + printWAVInfo(&wav); + printWAVInfo(&wav2); + samples = (U16*)wav2.data; + numsamples = wav2.size/2; + + /* the following is a big hack to prevent against + periods of total silence- these get written as + blocks of length 0 by bladeenc, which causes + the flashplayer to crash */ + + for(t=0;t %d blocks", numsamples/(blocksize*2)); + for(t=0;t Writing block %d", t); + block1 = &samples[(t*2+0)*blocksize]; + block2 = &samples[(t*2+1)*blocksize]; + swf_SetSoundStreamBlock(tag, block1, blocksize,1); + swf_SetSoundStreamBlock(tag, block2, blocksize,0); + tag = swf_InsertTag(tag, ST_SHOWFRAME); + } + + f = open(outputname,O_WRONLY|O_CREAT|O_TRUNC, 0644); + if FAILED(swf_WriteSWF(f,&swf)) fprintf(stderr,"WriteSWF() failed.\n"); + close(f); + + swf_FreeTags(&swf); + return 0; +} + + -- 1.7.10.4