diff --git a/.gitignore b/.gitignore index 573d4f3..a7a2375 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ encode decode +*.o 11025.ppm 11025.wav 40000.ppm diff --git a/Makefile b/Makefile index 3004f68..91c497b 100644 --- a/Makefile +++ b/Makefile @@ -1,25 +1,26 @@ CC = gcc -CFLAGS = -D_GNU_SOURCE= -W -Wall -O3 -std=c99 -lm -ffast-math +CFLAGS = -D_GNU_SOURCE= -W -Wall -O3 -std=c99 -ffast-math -DDN=1 -DUP=1 +LDFLAGS = $(CFLAGS) -lm -lasound all: encode decode -# ./encode smpte.ppm 8000.wav 8000 -# ./encode smpte.ppm 11025.wav 11025 -# ./encode smpte.ppm 40000.wav 40000 -# ./encode smpte.ppm 44100.wav 44100 -# ./encode smpte.ppm 48000.wav 48000 -# ./decode 8000.wav 8000.ppm -# ./decode 11025.wav 11025.ppm -# ./decode 40000.wav 40000.ppm -# ./decode 44100.wav 44100.ppm -# ./decode 48000.wav 48000.ppm + +test: all + ./encode smpte.ppm 8000.wav 8000 + ./encode smpte.ppm 11025.wav 11025 + ./encode smpte.ppm 40000.wav 40000 + ./encode smpte.ppm 44100.wav 44100 + ./encode smpte.ppm 48000.wav 48000 + ./decode wav:8000.wav 8000.ppm + ./decode wav:11025.wav 11025.ppm + ./decode wav:40000.wav 40000.ppm + ./decode wav:44100.wav 44100.ppm + ./decode wav:48000.wav 48000.ppm clean: - rm -f encode decode {8000,11025,40000,44100,48000}.{ppm,wav} + rm -f encode decode *.o {8000,11025,40000,44100,48000}.{ppm,wav} -encode: encode.c Makefile - $(CC) -o $@ $< $(CFLAGS) +encode: encode.o mmap_file.o -decode: decode.c Makefile - $(CC) -o $@ $< $(CFLAGS) -lasound -DDN=1 -DUP=1 +decode: decode.o mmap_file.o pcm.o wav.o alsa.o diff --git a/alsa.c b/alsa.c new file mode 100644 index 0000000..c6e3dd8 --- /dev/null +++ b/alsa.c @@ -0,0 +1,127 @@ + +#include +#include +#include +#include "alsa.h" + +typedef struct { + void (*close)(pcm_t *); + void (*info)(pcm_t *); + int (*rate)(pcm_t *); + int (*channels)(pcm_t *); + int (*read)(struct pcm *, short *, int); + snd_pcm_t *pcm; + int r; + int c; +} alsa_t; + +void close_alsa(pcm_t *pcm) +{ + alsa_t *alsa = (alsa_t *)pcm; + snd_pcm_close(alsa->pcm); +} + +void info_alsa(pcm_t *pcm) +{ + alsa_t *alsa = (alsa_t *)pcm; + fprintf(stderr, "%d channel(s), %d rate\n", alsa->c, alsa->r); +} +int rate_alsa(pcm_t *pcm) +{ + alsa_t *alsa = (alsa_t *)pcm; + return alsa->r; +} +int channels_alsa(pcm_t *pcm) +{ + alsa_t *alsa = (alsa_t *)pcm; + return alsa->c; +} +int read_alsa(pcm_t *pcm, short *buff, int frames) +{ + alsa_t *alsa = (alsa_t *)pcm; + int got = 0; + while (0 < frames) { + while ((got = snd_pcm_readi(alsa->pcm, buff, frames)) < 0) { + snd_pcm_prepare(alsa->pcm); + fprintf(stderr, "<<<<<<<<<<<<<<< Buffer Overrun >>>>>>>>>>>>>>>\n"); + } + buff += got * alsa->c; + frames -= got; + } + return 1; +} + +int open_alsa(pcm_t **p, char *name) +{ + alsa_t *alsa = (alsa_t *)malloc(sizeof(alsa_t)); + alsa->close = close_alsa; + alsa->info = info_alsa; + alsa->rate = rate_alsa; + alsa->channels = channels_alsa; + alsa->read = read_alsa; + + snd_pcm_t *pcm; + snd_pcm_hw_params_t *params; + snd_pcm_hw_params_alloca(¶ms); + + if (snd_pcm_open(&pcm, name, SND_PCM_STREAM_CAPTURE, 0) < 0) { + fprintf(stderr, "Error opening PCM device %s\n", name); + free(alsa); + return 0; + } + + if (snd_pcm_hw_params_any(pcm, params) < 0) { + fprintf(stderr, "Can not configure this PCM device.\n"); + snd_pcm_close(alsa->pcm); + free(alsa); + return 0; + } + + if (snd_pcm_hw_params_set_access(pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) { + fprintf(stderr, "Error setting access.\n"); + snd_pcm_close(alsa->pcm); + free(alsa); + return 0; + } + + if (snd_pcm_hw_params_set_format(pcm, params, SND_PCM_FORMAT_S16_LE) < 0) { + fprintf(stderr, "Error setting S16_LE format.\n"); + snd_pcm_close(alsa->pcm); + free(alsa); + return 0; + } + + if (snd_pcm_hw_params_set_rate_resample(pcm, params, 0) < 0) { + fprintf(stderr, "Error disabling resampling.\n"); + snd_pcm_close(alsa->pcm); + free(alsa); + return 0; + } + + if (snd_pcm_hw_params(pcm, params) < 0) { + fprintf(stderr, "Error setting HW params.\n"); + snd_pcm_close(alsa->pcm); + free(alsa); + return 0; + } + unsigned int rate = 0; + if (snd_pcm_hw_params_get_rate(params, &rate, 0) < 0) { + fprintf(stderr, "Error getting rate.\n"); + snd_pcm_close(alsa->pcm); + free(alsa); + return 0; + } + unsigned int channels = 0; + if (snd_pcm_hw_params_get_channels(params, &channels) < 0) { + fprintf(stderr, "Error getting channels.\n"); + snd_pcm_close(alsa->pcm); + free(alsa); + return 0; + } + alsa->pcm = pcm; + alsa->r = rate; + alsa->c = channels; + *p = (pcm_t *)alsa; + return 1; +} + diff --git a/alsa.h b/alsa.h new file mode 100644 index 0000000..6971e0e --- /dev/null +++ b/alsa.h @@ -0,0 +1,7 @@ + +#ifndef ALSA_H +#define ALSA_H +#include "pcm.h" +int open_alsa(pcm_t **, char *); +#endif + diff --git a/decode.c b/decode.c index 0a43a0e..58cbb12 100644 --- a/decode.c +++ b/decode.c @@ -3,15 +3,11 @@ #include #include #include -#include -#include -#include -#include -#include #include #include -#include #include +#include "mmap_file.h" +#include "pcm.h" float lerp(float a, float b, float x) { @@ -190,92 +186,6 @@ void free_delay(delay_t *delay) free(delay); } -void *mmap_file_ro(char *name, size_t *size) -{ - *size = 0; - int fd = open(name, O_RDONLY); - if (fd == -1) { - perror("open"); - return 0; - } - - struct stat sb; - if (fstat(fd, &sb) == -1) { - perror("fstat"); - return 0; - } - - if (!S_ISREG(sb.st_mode)) { - fprintf(stderr, "%s not a file\n", name); - return 0; - } - - void *p = mmap(0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0); - if (p == MAP_FAILED) { - perror("mmap"); - return 0; - } - - if (close(fd) == -1) { - perror("close"); - return 0; - } - *size = sb.st_size; - fprintf(stderr, "opened %s (ro)\n", name); - return p; -} - -void *mmap_file_rw(char *name, size_t size) -{ - int fd = open(name, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); - if (fd == -1) { - perror("open"); - return 0; - } - - struct stat sb; - if (fstat(fd, &sb) == -1) { - perror("fstat"); - return 0; - } - - if (!S_ISREG(sb.st_mode)) { - fprintf(stderr, "%s not a file\n", name); - return 0; - } - - if (lseek(fd, size - 1, SEEK_SET) == -1) { - perror("lseek"); - return 0; - } - - if (write(fd, "", 1) != 1) { - perror("write"); - return 0; - } - - void *p = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); - if (p == MAP_FAILED) { - perror("mmap"); - return 0; - } - - if (close(fd) == -1) { - perror ("close"); - return 0; - } - fprintf(stderr, "opened %s (rw)\n", name); - return p; -} -int munmap_file(void *p, size_t size) -{ - if (munmap(p, size) == -1) { - perror("munmap"); - return 0; - } - return 1; -} - typedef struct { uint32_t ChunkID; uint32_t ChunkSize; @@ -324,82 +234,6 @@ void process_line(uint8_t *pixel, uint8_t *y_pixel, uint8_t *uv_pixel, int y_wid } } -typedef struct { - snd_pcm_t *pcm; - int rate; - int channels; -} pcm_t; - -pcm_t *open_pcm(char *name) -{ - snd_pcm_t *pcm; - snd_pcm_hw_params_t *params; - snd_pcm_hw_params_alloca(¶ms); - - if (snd_pcm_open(&pcm, name, SND_PCM_STREAM_CAPTURE, 0) < 0) { - fprintf(stderr, "Error opening PCM device\n"); - return 0; - } - - if (snd_pcm_hw_params_any(pcm, params) < 0) { - fprintf(stderr, "Can not configure this PCM device.\n"); - return 0; - } - - if (snd_pcm_hw_params_set_access(pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) { - fprintf(stderr, "Error setting access.\n"); - return 0; - } - - if (snd_pcm_hw_params_set_format(pcm, params, SND_PCM_FORMAT_S16_LE) < 0) { - fprintf(stderr, "Error setting format.\n"); - return 0; - } - - if (snd_pcm_hw_params_set_rate_resample(pcm, params, 0) < 0) { - fprintf(stderr, "Error disabling resampling.\n"); - return 0; - } - - if (snd_pcm_hw_params(pcm, params) < 0) { - fprintf(stderr, "Error setting HW params.\n"); - return 0; - } - unsigned int rate = 0; - if (snd_pcm_hw_params_get_rate(params, &rate, 0) < 0) { - fprintf(stderr, "Error getting rate.\n"); - return 0; - } - unsigned int channels = 0; - if (snd_pcm_hw_params_get_channels(params, &channels) < 0) { - fprintf(stderr, "Error getting channels.\n"); - return 0; - } - pcm_t *p = (pcm_t *)malloc(sizeof(pcm_t)); - p->pcm = pcm; - p->rate = rate; - p->channels = channels; - return p; -} - -void close_pcm(pcm_t *p) -{ - snd_pcm_close(p->pcm); - free(p); -} -void read_pcm(pcm_t *p, short *buff, int frames) -{ - int got = 0; - while (0 < frames) { - while ((got = snd_pcm_readi(p->pcm, buff, frames)) < 0) { - snd_pcm_prepare(p->pcm); - fprintf(stderr, "<<<<<<<<<<<<<<< Buffer Overrun >>>>>>>>>>>>>>>\n"); - } - buff += got * p->channels; - frames -= got; - } -} - char *string_time(char *fmt) { static char s[64]; @@ -411,22 +245,26 @@ char *string_time(char *fmt) int main(int argc, char **argv) { pcm_t *pcm; - if (argc == 1) - pcm = open_pcm("default"); - else - pcm = open_pcm(argv[1]); + char *name = "alsa:default"; + if (argc != 1) + name = argv[1]; - if (!pcm) + if (!open_pcm(&pcm, name)) { + fprintf(stderr, "couldnt open %s\n", name); return 1; + } - float rate = pcm->rate; + info_pcm(pcm); + + float rate = rate_pcm(pcm); if (rate * 0.088 < 320.0) { fprintf(stderr, "%.0fhz samplerate too low\n", rate); return 1; } - fprintf(stderr, "%.0fhz samplerate\n", rate); - if (pcm->channels > 1) - fprintf(stderr, "using first of %d channels\n", pcm->channels); + + int channels = channels_pcm(pcm); + if (channels > 1) + fprintf(stderr, "using first of %d channels\n", channels); const float step = 1.0 / rate; float complex cnt_last = -I; @@ -488,7 +326,7 @@ int main(int argc, char **argv) delay_t *cnt_delay = alloc_delay((dat_taps - 1) / (2 * factor_L)); delay_t *dat_delay = alloc_delay((cnt_taps - 1) / (2 * factor_L)); - short *buff = (short *)malloc(sizeof(short) * pcm->channels * factor_M); + short *buff = (short *)malloc(sizeof(short) * channels * factor_M); const float sync_porch_len = 0.003; const float porch_len = 0.0015; (void)porch_len; @@ -504,7 +342,7 @@ int main(int argc, char **argv) char ppm_head[32]; snprintf(ppm_head, 32, "P6 %d %d 255\n", width, height); size_t ppm_size = strlen(ppm_head) + width * height * 3; - char *ppm_p = 0; + void *ppm_p = 0; uint8_t *pixel = 0; int hor_ticks = 0; @@ -520,9 +358,10 @@ int main(int argc, char **argv) for (int out = factor_L;; out++, hor_ticks++, cal_ticks++, vis_ticks++) { if (out >= factor_L) { out = 0; - read_pcm(pcm, buff, factor_M); + if (!read_pcm(pcm, buff, factor_M)) + break; for (int j = 0; j < factor_M; j++) { - float amp = (float)buff[j * pcm->channels] / 32767.0; + float amp = (float)buff[j * channels] / 32767.0; cnt_amp[j] = do_delay(cnt_delay, amp); dat_amp[j] = do_delay(dat_delay, amp); } @@ -647,7 +486,7 @@ int main(int argc, char **argv) missing_sync = 0; seperator_correction = 0; } - ppm_p = mmap_file_rw(string_time("%F_%T.ppm"), ppm_size); + mmap_file_rw(&ppm_p, string_time("%F_%T.ppm"), ppm_size); memcpy(ppm_p, ppm_head, strlen(ppm_head)); pixel = (uint8_t *)ppm_p + strlen(ppm_head); memset(pixel, 0, width * height * 3); @@ -734,6 +573,13 @@ int main(int argc, char **argv) uv_pixel[uv_pixel_x++ + odd * uv_width] = limit(0.0, 255.0, 255.0 * (dat_freq - 1500.0) / 800.0); } + if (pixel) { + munmap_file(ppm_p, ppm_size); + fprintf(stderr, "%d missing sync's and %d corrections from seperator\n", missing_sync, seperator_correction); + missing_sync = 0; + seperator_correction = 0; + } + close_pcm(pcm); free_ddc(cnt_ddc); diff --git a/encode.c b/encode.c index 3c349b8..6dec237 100644 --- a/encode.c +++ b/encode.c @@ -3,14 +3,10 @@ #include #include #include -#include -#include -#include -#include -#include #include #include #include +#include "mmap_file.h" float limit(float min, float max, float x) { @@ -49,91 +45,6 @@ uint8_t U_RGB(uint8_t R, uint8_t G, uint8_t B) return limit(0.0, 255.0, 128.0 + (0.003906 * ((-37.945 * R) + (-74.494 * G) + (112.439 * B)))); } -void *mmap_file_ro(char *name, size_t *size) -{ - *size = 0; - int fd = open(name, O_RDONLY); - if (fd == -1) { - perror("open"); - return 0; - } - - struct stat sb; - if (fstat(fd, &sb) == -1) { - perror("fstat"); - return 0; - } - - if (!S_ISREG(sb.st_mode)) { - fprintf(stderr, "%s not a file\n", name); - return 0; - } - - void *p = mmap(0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0); - if (p == MAP_FAILED) { - perror("mmap"); - return 0; - } - - if (close(fd) == -1) { - perror ("close"); - return 0; - } - *size = sb.st_size; - return p; -} - -void *mmap_file_rw(char *name, size_t size) -{ - int fd = open(name, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); - if (fd == -1) { - perror("open"); - return 0; - } - - struct stat sb; - if (fstat(fd, &sb) == -1) { - perror("fstat"); - return 0; - } - - if (!S_ISREG(sb.st_mode)) { - fprintf(stderr, "%s not a file\n", name); - return 0; - } - - if (lseek(fd, size - 1, SEEK_SET) == -1) { - perror("lseek"); - return 0; - } - - if (write(fd, "", 1) != 1) { - perror("write"); - return 0; - } - - void *p = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); - if (p == MAP_FAILED) { - perror("mmap"); - return 0; - } - - if (close(fd) == -1) { - perror ("close"); - return 0; - } - return p; -} - -int munmap_file(void *p, size_t size) -{ - if (munmap(p, size) == -1) { - perror("munmap"); - return 0; - } - return 1; -} - typedef struct { uint32_t ChunkID; uint32_t ChunkSize; @@ -176,7 +87,11 @@ int main(int argc, char **argv) } size_t ppm_size; - char *ppm_p = mmap_file_ro(argv[1], &ppm_size); + void *ppm_p; + if (!mmap_file_ro(&ppm_p, argv[1], &ppm_size)) { + fprintf(stderr, "couldnt open ppm file\n"); + return 1; + } const int width = 320; const int height = 240; const char *ppm_head = "P6 320 240 255\n"; @@ -201,9 +116,11 @@ int main(int argc, char **argv) size_t wav_size = 4096 * ((size_t)(37.5 * rate * 2 + 44 + 4095) / 4096); int samples = (wav_size - 44) / 2; - char *wav_p = mmap_file_rw(argv[2], wav_size); - if (!wav_p) + void *wav_p; + if (!mmap_file_rw(&wav_p, argv[2], wav_size)) { + fprintf(stderr, "couldnt open wav file\n"); return 1; + } buffer = (short *)(wav_p + sizeof(wav_t)); diff --git a/mmap_file.c b/mmap_file.c new file mode 100644 index 0000000..9534c73 --- /dev/null +++ b/mmap_file.c @@ -0,0 +1,100 @@ + +#include +#include +#include +#include +#include +#include "mmap_file.h" + +int mmap_file_ro(void **p, char *name, size_t *size) +{ + *size = 0; + int fd = open(name, O_RDONLY); + if (fd == -1) { + perror("open"); + return 0; + } + + struct stat sb; + if (fstat(fd, &sb) == -1) { + perror("fstat"); + close(fd); + return 0; + } + + if (!S_ISREG(sb.st_mode)) { + fprintf(stderr, "%s not a file\n", name); + close(fd); + return 0; + } + + *p = mmap(0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0); + if (*p == MAP_FAILED) { + perror("mmap"); + close(fd); + return 0; + } + + if (close(fd) == -1) { + perror ("close"); + return 0; + } + *size = sb.st_size; + return 1; +} + +int mmap_file_rw(void **p, char *name, size_t size) +{ + int fd = open(name, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + if (fd == -1) { + perror("open"); + return 0; + } + + struct stat sb; + if (fstat(fd, &sb) == -1) { + perror("fstat"); + close(fd); + return 0; + } + + if (!S_ISREG(sb.st_mode)) { + fprintf(stderr, "%s not a file\n", name); + close(fd); + return 0; + } + + if (lseek(fd, size - 1, SEEK_SET) == -1) { + perror("lseek"); + close(fd); + return 0; + } + + if (write(fd, "", 1) != 1) { + perror("write"); + close(fd); + return 0; + } + + *p = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (*p == MAP_FAILED) { + perror("mmap"); + close(fd); + return 0; + } + + if (close(fd) == -1) { + perror ("close"); + return 0; + } + return 1; +} +int munmap_file(void *p, size_t size) +{ + if (munmap(p, size) == -1) { + perror("munmap"); + return 0; + } + return 1; +} + diff --git a/mmap_file.h b/mmap_file.h new file mode 100644 index 0000000..b18fd68 --- /dev/null +++ b/mmap_file.h @@ -0,0 +1,6 @@ +#ifndef MMAP_FILE_H +#define MMAP_FILE_H +int mmap_file_ro(void **, char *, size_t *); +int mmap_file_rw(void **, char *, size_t); +int munmap_file(void *, size_t); +#endif diff --git a/pcm.c b/pcm.c new file mode 100644 index 0000000..6a7b583 --- /dev/null +++ b/pcm.c @@ -0,0 +1,43 @@ + +#include +#include +#include +#include "pcm.h" +#include "alsa.h" +#include "wav.h" + +void close_pcm(pcm_t *pcm) +{ + pcm->close(pcm); + free(pcm); +} + +void info_pcm(pcm_t *pcm) +{ + pcm->info(pcm); +} + +int rate_pcm(pcm_t *pcm) +{ + return pcm->rate(pcm); +} + +int channels_pcm(pcm_t *pcm) +{ + return pcm->channels(pcm); +} + +int read_pcm(pcm_t *pcm, short *buff, int frames) +{ + return pcm->read(pcm, buff, frames); +} + +int open_pcm(pcm_t **p, char *name) +{ + if (strstr(name, "alsa:")) + return open_alsa(p, name + strlen("alsa:")); + if (strstr(name, "wav:")) + return open_wav(p, name + strlen("wav:")); + return 0; +} + diff --git a/pcm.h b/pcm.h new file mode 100644 index 0000000..8dc803f --- /dev/null +++ b/pcm.h @@ -0,0 +1,21 @@ + +#ifndef PCM_H +#define PCM_H + +typedef struct pcm { + void (*close)(struct pcm *); + void (*info)(struct pcm *); + int (*rate)(struct pcm *); + int (*channels)(struct pcm *); + int (*read)(struct pcm *, short *, int); +} pcm_t; + +void close_pcm(pcm_t *); +void info_pcm(pcm_t *); +int rate_pcm(pcm_t *); +int channels_pcm(pcm_t *); +int read_pcm(pcm_t *, short *, int); +int open_pcm(pcm_t **, char *); + +#endif + diff --git a/wav.c b/wav.c new file mode 100644 index 0000000..a94d3eb --- /dev/null +++ b/wav.c @@ -0,0 +1,108 @@ + +#include +#include +#include +#include +#include "wav.h" +#include "mmap_file.h" + +typedef struct { + uint32_t ChunkID; + uint32_t ChunkSize; + uint32_t Format; + uint32_t Subchunk1ID; + uint32_t Subchunk1Size; + uint16_t AudioFormat; + uint16_t NumChannels; + uint32_t SampleRate; + uint32_t ByteRate; + uint16_t BlockAlign; + uint16_t BitsPerSample; + uint32_t Subchunk2ID; + uint32_t Subchunk2Size; +} wav_head_t; + +typedef struct { + void (*close)(pcm_t *); + void (*info)(pcm_t *); + int (*rate)(pcm_t *); + int (*channels)(pcm_t *); + int (*read)(struct pcm *, short *, int); + void *p; + short *b; + size_t size; + int r; + int c; + int samples; + int index; +} wav_t; + +void close_wav(pcm_t *pcm) +{ + wav_t *wav = (wav_t *)pcm; + munmap_file(wav->p, wav->size); +} + +void info_wav(pcm_t *pcm) +{ + wav_t *wav = (wav_t *)pcm; + fprintf(stderr, "%d channel(s), %d rate, %d samples\n", wav->c, wav->r, wav->samples); +} +int rate_wav(pcm_t *pcm) +{ + wav_t *wav = (wav_t *)pcm; + return wav->r; +} +int channels_wav(pcm_t *pcm) +{ + wav_t *wav = (wav_t *)pcm; + return wav->c; +} +int read_wav(pcm_t *pcm, short *buff, int frames) +{ + wav_t *wav = (wav_t *)pcm; + if ((wav->index + frames * wav->c) > wav->samples) + return 0; + memcpy(buff, wav->b + wav->index, sizeof(short) * frames * wav->c); + wav->index += frames * wav->c; + return 1; +} + +int open_wav(pcm_t **p, char *name) +{ + wav_t *wav = (wav_t *)malloc(sizeof(wav_t)); + wav->close = close_wav; + wav->info = info_wav; + wav->rate = rate_wav; + wav->channels = channels_wav; + wav->read = read_wav; + if (!mmap_file_ro(&wav->p, name, &wav->size)) { + fprintf(stderr, "couldnt open wav file %s!\n", name); + free(wav); + return 0; + } + wav_head_t *head = (wav_head_t *)wav->p; + wav->b = (short *)(wav->p + sizeof(wav_head_t)); + + if (head->ChunkID != 0x46464952 || head->Format != 0x45564157 || + head->Subchunk1ID != 0x20746d66 || head->Subchunk1Size != 16 || + head->AudioFormat != 1 || head->Subchunk2ID != 0x61746164) { + fprintf(stderr, "unsupported WAV file!\n"); + munmap_file(wav->p, wav->size); + free(wav); + return 0; + } + if (head->BitsPerSample != 16) { + fprintf(stderr, "only 16bit WAV supported!\n"); + munmap_file(wav->p, wav->size); + free(wav); + return 0; + } + wav->c = head->NumChannels; + wav->samples = head->Subchunk2Size / 2; + wav->index = 0; + wav->r = head->SampleRate; + *p = (pcm_t *)wav; + return 1; +} + diff --git a/wav.h b/wav.h new file mode 100644 index 0000000..6f0805e --- /dev/null +++ b/wav.h @@ -0,0 +1,6 @@ + +#ifndef WAV_H +#define WAV_H +#include "pcm.h" +int open_wav(pcm_t **, char *); +#endif