00001 #include <endian.h>
00002 #include <byteswap.h>
00003
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
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
00038
00039
00040
00041 typedef struct {
00042 u_int magic;
00043 u_int length;
00044 u_int type;
00045 } WaveHeader;
00046
00047 typedef struct {
00048 u_short format;
00049 u_short modus;
00050 u_int sample_fq;
00051 u_int byte_p_sec;
00052 u_short byte_p_spl;
00053 u_short bit_p_spl;
00054 } WaveFmtBody;
00055
00056 typedef struct {
00057 u_int type;
00058 u_int length;
00059 } WaveChunkHeader;
00060
00061 long long fdcount = 0;
00062
00063
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
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
00095
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
00129
00130 }
00131
00132 return 0;
00133 }
00134
00135 static void end_wave(int fd) {
00136
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 }