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         switch ((unsigned long) state->audio_format) {
00078         case SND_PCM_FORMAT_U8:
00079                 bits = 8;
00080                 break;
00081         case SND_PCM_FORMAT_S16_LE:
00082         case SND_PCM_FORMAT_S16_BE:
00083                 bits = 16;
00084                 break;
00085         case SND_PCM_FORMAT_S32_LE:
00086                 bits = 32;
00087                 break;
00088         case SND_PCM_FORMAT_S24_LE:
00089         case SND_PCM_FORMAT_S24_3LE:
00090                 bits = 24;
00091                 break;
00092         default:
00093                 return -1;
00094 //              error(_("Wave doesn't support %s format..."), snd_pcm_format_name(state->audio_format));
00095 //              exit(EXIT_FAILURE);
00096         }
00097         h.magic = WAV_RIFF;
00098         tmp = cnt + sizeof(WaveHeader) + sizeof(WaveChunkHeader) + sizeof(WaveFmtBody) + sizeof(WaveChunkHeader) - 8;
00099         h.length = LE_INT(tmp);
00100         h.type = WAV_WAVE;
00101 
00102         cf.type = WAV_FMT;
00103         cf.length = LE_INT(16);
00104 
00105         f.format = LE_SHORT(WAV_PCM_CODE);
00106         f.modus = LE_SHORT(state->audio_channels);
00107         f.sample_fq = LE_INT(state->audio_rate);
00108 #if 0
00109         tmp2 = (samplesize == 8) ? 1 : 2;
00110         f.byte_p_spl = LE_SHORT(tmp2);
00111         tmp = dsp_speed * hwparams.channels * (u_int) tmp2;
00112 #else
00113         tmp2 = state->audio_channels * snd_pcm_format_physical_width(state->audio_format) / 8;
00114         f.byte_p_spl = LE_SHORT(tmp2);
00115         tmp = (u_int) tmp2 * state->audio_rate;
00116 #endif
00117         f.byte_p_sec = LE_INT(tmp);
00118         f.bit_p_spl = LE_SHORT(bits);
00119 
00120         cd.type = WAV_DATA;
00121         cd.length = LE_INT(cnt);
00122 
00123         if(write(fd, &h, sizeof(WaveHeader)) != sizeof(WaveHeader) ||
00124                 write(fd, &cf, sizeof(WaveChunkHeader)) != sizeof(WaveChunkHeader) ||
00125                 write(fd, &f, sizeof(WaveFmtBody)) != sizeof(WaveFmtBody) ||
00126                 write(fd, &cd, sizeof(WaveChunkHeader)) != sizeof(WaveChunkHeader)) {
00127                 return -2;
00128 //              error(_("write error"));
00129 //              exit(EXIT_FAILURE);
00130         }
00131 
00132         return 0;
00133 }
00134 
00135 static void end_wave(int fd) {
00136         /* only close output */
00137         WaveChunkHeader cd;
00138         off_t length_seek;
00139         off_t filelen;
00140         u_int rifflen;
00141         
00142         length_seek = sizeof(WaveHeader) + sizeof(WaveChunkHeader) + sizeof(WaveFmtBody);
00143         cd.type = WAV_DATA;
00144         cd.length = fdcount > 0x7fffffff ? LE_INT(0x7fffffff) : LE_INT(fdcount);
00145         filelen = fdcount + 2*sizeof(WaveChunkHeader) + sizeof(WaveFmtBody) + 4;
00146         rifflen = filelen > 0x7fffffff ? LE_INT(0x7fffffff) : LE_INT(filelen);
00147         if(lseek(fd, 4, SEEK_SET) == 4)
00148                 write(fd, &rifflen, 4);
00149         if(lseek(fd, length_seek, SEEK_SET) == length_seek)
00150                 write(fd, &cd, sizeof(WaveChunkHeader));
00151         if(fd != 1)
00152                 close(fd);
00153 }
00154 
00155 int wave_fd;
00156 
00157 void wave_begin(const char *fname) {
00158         wave_fd = open(fname, O_RDWR | O_CREAT);
00159         int r = begin_wave(wave_fd, 0);
00160 fprintf(stderr, "fname == \"%s\", wave_fd == %d, begin_wave() == %d\n", fname, wave_fd, r);
00161 }
00162 
00163 void wave_push(void *buf, int len) {
00164         fdcount += write(wave_fd, buf, len);
00165 }
00166 
00167 void wave_end() {
00168         end_wave(wave_fd);
00169 }

Generated on Fri Nov 28 00:06:21 2008 for elphel by  doxygen 1.5.1