apps/camogm2/camogm_wav.c

Go to the documentation of this file.
00001 #include <endian.h>
00002 #include <byteswap.h>
00003 //#define _LARGEFILE64_SOURCE
00004 #include <sys/types.h>
00005 #include <unistd.h>
00006 #include <stdio.h>
00007 
00008 #include "camogm_wav.h"
00009 #include "camogm.h"
00010 
00011 #include <alsa/asoundlib.h>
00012 
00013 /* Definitions for Microsoft WAVE format */
00014 
00015 #if __BYTE_ORDER == __LITTLE_ENDIAN
00016 #define COMPOSE_ID(a,b,c,d)     ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))
00017 #define LE_SHORT(v)             (v)
00018 #define LE_INT(v)               (v)
00019 #define BE_SHORT(v)             bswap_16(v)
00020 #define BE_INT(v)               bswap_32(v)
00021 #elif __BYTE_ORDER == __BIG_ENDIAN
00022 #define COMPOSE_ID(a,b,c,d)     ((d) | ((c)<<8) | ((b)<<16) | ((a)<<24))
00023 #define LE_SHORT(v)             bswap_16(v)
00024 #define LE_INT(v)               bswap_32(v)
00025 #define BE_SHORT(v)             (v)
00026 #define BE_INT(v)               (v)
00027 #else
00028 #error "Wrong endian"
00029 #endif
00030 
00031 #define WAV_RIFF                COMPOSE_ID('R','I','F','F')
00032 #define WAV_WAVE                COMPOSE_ID('W','A','V','E')
00033 #define WAV_FMT                 COMPOSE_ID('f','m','t',' ')
00034 #define WAV_DATA                COMPOSE_ID('d','a','t','a')
00035 #define WAV_PCM_CODE            1
00036 
00037 /* it's in chunks like .voc and AMIGA iff, but my source say there
00038    are in only in this combination, so I combined them in one header;
00039    it works on all WAVE-file I have
00040  */
00041 typedef struct {
00042         u_int magic;            /* 'RIFF' */
00043         u_int length;           /* filelen */
00044         u_int type;             /* 'WAVE' */
00045 } WaveHeader;
00046 
00047 typedef struct {
00048         u_short format;         /* should be 1 for PCM-code */
00049         u_short modus;          /* 1 Mono, 2 Stereo */
00050         u_int sample_fq;        /* frequence of sample */
00051         u_int byte_p_sec;
00052         u_short byte_p_spl;     /* samplesize; 1 or 2 bytes */
00053         u_short bit_p_spl;      /* 8, 12 or 16 bit */
00054 } WaveFmtBody;
00055 
00056 typedef struct {
00057         u_int type;             /* 'data' */
00058         u_int length;           /* samplecount */
00059 } WaveChunkHeader;
00060 
00061 long long fdcount = 0;
00062 
00063 /* write a WAVE-header */
00064 static int begin_wave(int fd, size_t cnt) {
00065         WaveHeader h;
00066         WaveFmtBody f;
00067         WaveChunkHeader cf, cd;
00068         int bits;
00069         u_int tmp;
00070         u_short tmp2;
00071 
00072         /* WAVE cannot handle greater than 32bit (signed?) int */
00073         if(cnt == (size_t) - 2)
00074                 cnt = 0x7fffff00;
00075 
00076         bits = 8;
00077         unsigned long audio_format = SND_PCM_FORMAT_S16_LE;
00078 //      switch ((unsigned long) state->audio_format) {
00079         switch ((unsigned long) audio_format) {
00080         case SND_PCM_FORMAT_U8:
00081                 bits = 8;
00082                 break;
00083         case SND_PCM_FORMAT_S16_LE:
00084         case SND_PCM_FORMAT_S16_BE:
00085                 bits = 16;
00086                 break;
00087         case SND_PCM_FORMAT_S32_LE:
00088                 bits = 32;
00089                 break;
00090         case SND_PCM_FORMAT_S24_LE:
00091         case SND_PCM_FORMAT_S24_3LE:
00092                 bits = 24;
00093                 break;
00094         default:
00095                 return -1;
00096 //              error(_("Wave doesn't support %s format..."), snd_pcm_format_name(state->audio_format));
00097 //              exit(EXIT_FAILURE);
00098         }
00099         h.magic = WAV_RIFF;
00100         tmp = cnt + sizeof(WaveHeader) + sizeof(WaveChunkHeader) + sizeof(WaveFmtBody) + sizeof(WaveChunkHeader) - 8;
00101         h.length = LE_INT(tmp);
00102         h.type = WAV_WAVE;
00103 
00104         cf.type = WAV_FMT;
00105         cf.length = LE_INT(16);
00106 
00107         f.format = LE_SHORT(WAV_PCM_CODE);
00108         f.modus = LE_SHORT(state->audio_channels);
00109         f.sample_fq = LE_INT(state->audio_rate);
00110 #if 0
00111         tmp2 = (samplesize == 8) ? 1 : 2;
00112         f.byte_p_spl = LE_SHORT(tmp2);
00113         tmp = dsp_speed * hwparams.channels * (u_int) tmp2;
00114 #else
00115 //      tmp2 = state->audio_channels * snd_pcm_format_physical_width(state->audio_format) / 8;
00116         tmp2 = state->audio_channels * snd_pcm_format_physical_width(audio_format) / 8;
00117         f.byte_p_spl = LE_SHORT(tmp2);
00118         tmp = (u_int) tmp2 * state->audio_rate;
00119 #endif
00120         f.byte_p_sec = LE_INT(tmp);
00121         f.bit_p_spl = LE_SHORT(bits);
00122 
00123         cd.type = WAV_DATA;
00124         cd.length = LE_INT(cnt);
00125 
00126         if(write(fd, &h, sizeof(WaveHeader)) != sizeof(WaveHeader) ||
00127                 write(fd, &cf, sizeof(WaveChunkHeader)) != sizeof(WaveChunkHeader) ||
00128                 write(fd, &f, sizeof(WaveFmtBody)) != sizeof(WaveFmtBody) ||
00129                 write(fd, &cd, sizeof(WaveChunkHeader)) != sizeof(WaveChunkHeader)) {
00130                 return -2;
00131 //              error(_("write error"));
00132 //              exit(EXIT_FAILURE);
00133         }
00134 
00135         return 0;
00136 }
00137 
00138 static void end_wave(int fd) {
00139         /* only close output */
00140         WaveChunkHeader cd;
00141         off_t length_seek;
00142         off_t filelen;
00143         u_int rifflen;
00144         
00145         length_seek = sizeof(WaveHeader) + sizeof(WaveChunkHeader) + sizeof(WaveFmtBody);
00146         cd.type = WAV_DATA;
00147         cd.length = fdcount > 0x7fffffff ? LE_INT(0x7fffffff) : LE_INT(fdcount);
00148         filelen = fdcount + 2*sizeof(WaveChunkHeader) + sizeof(WaveFmtBody) + 4;
00149         rifflen = filelen > 0x7fffffff ? LE_INT(0x7fffffff) : LE_INT(filelen);
00150         if(lseek(fd, 4, SEEK_SET) == 4)
00151                 write(fd, &rifflen, 4);
00152         if(lseek(fd, length_seek, SEEK_SET) == length_seek)
00153                 write(fd, &cd, sizeof(WaveChunkHeader));
00154         if(fd != 1)
00155                 close(fd);
00156 }
00157 
00158 int wave_fd;
00159 
00160 void wave_begin(const char *fname) {
00161         wave_fd = open(fname, O_RDWR | O_CREAT);
00162         int r = begin_wave(wave_fd, 0);
00163 fprintf(stderr, "fname == \"%s\", wave_fd == %d, begin_wave() == %d\n", fname, wave_fd, r);
00164 }
00165 
00166 void wave_push(void *buf, int len) {
00167         fdcount += write(wave_fd, buf, len);
00168 }
00169 
00170 void wave_end() {
00171         end_wave(wave_fd);
00172 }

Generated on Thu Aug 7 16:18:59 2008 for elphel by  doxygen 1.5.1