initial revision
authorkramm <kramm>
Mon, 18 Mar 2002 10:37:32 +0000 (10:37 +0000)
committerkramm <kramm>
Mon, 18 Mar 2002 10:37:32 +0000 (10:37 +0000)
src/wav.c [new file with mode: 0644]
src/wav.h [new file with mode: 0644]
src/wav2swf.c [new file with mode: 0644]

diff --git a/src/wav.c b/src/wav.c
new file mode 100644 (file)
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 <kramm@quiss.org>
+
+   This file is distributed under the GPL, see file COPYING for details */
+
+#include <stdlib.h>
+#include <stdio.h>
+#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; i<src->size; 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; i<src->size; i+=channels) {
+               int j;
+               int pos2 = ((int)pos)*2;
+               for(j=0;j<fill;j+=2) {
+                   dest->data[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; i<src->size/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; i<src->size/2; i+=channels) {
+               int j;
+               int pos2 = ((int)pos)*2;
+               for(j=0;j<fill;j+=2) {
+                   dest->data[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; i<src->size/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; i<src->size/4; i+=channels) {
+               int j;
+               int pos2 = ((int)pos)*2;
+               for(j=0;j<fill;j+=2) {
+                   dest->data[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 (file)
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 <kramm@quiss.org>
+
+   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 (file)
index 0000000..6bf2ec7
--- /dev/null
@@ -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 <kramm@quiss.org>
+
+   This file is distributed under the GPL, see file COPYING for details */
+
+#include <stdlib.h>
+#include <stdio.h>
+#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("<fatal> 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<wav2.size/2;t+=2)
+      wav2.data[t]^=(t&2)<<1;
+
+  memset(&swf,0x00,sizeof(SWF));
+
+  swf.fileVersion    = 4;
+  swf.frameRate      = 44100*256/(blocksize*2);
+
+  swf.movieSize.xmax = 20*width;
+  swf.movieSize.ymax = 20*height;
+
+  swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
+  tag = swf.firstTag;
+  rgb.r = 0xff;
+  rgb.g = 0xff;
+  rgb.b = 0xff;
+  swf_SetRGB(tag,&rgb);
+
+  tag = swf_InsertTag(tag, ST_SOUNDSTREAMHEAD);
+  swf_SetSoundStreamHead(tag, blocksize);
+
+  logf("<notice> %d blocks", numsamples/(blocksize*2));
+  for(t=0;t<numsamples/(blocksize*2);t++) {
+      int s;
+      U16*block1;
+      U16*block2;
+      tag = swf_InsertTag(tag, ST_SOUNDSTREAMBLOCK);
+      logf("<notice> 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;
+}
+
+