mirror of
https://github.com/xdsopl/robot36.git
synced 2026-01-02 14:39:58 +01:00
splited into modules, added wav: and alsa: prefix for filename
This commit is contained in:
parent
2842fa7f61
commit
15b01cf36c
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,5 +1,6 @@
|
|||
encode
|
||||
decode
|
||||
*.o
|
||||
11025.ppm
|
||||
11025.wav
|
||||
40000.ppm
|
||||
|
|
|
|||
33
Makefile
33
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
|
||||
|
||||
|
|
|
|||
127
alsa.c
Normal file
127
alsa.c
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <alsa/asoundlib.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
7
alsa.h
Normal file
7
alsa.h
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
#ifndef ALSA_H
|
||||
#define ALSA_H
|
||||
#include "pcm.h"
|
||||
int open_alsa(pcm_t **, char *);
|
||||
#endif
|
||||
|
||||
210
decode.c
210
decode.c
|
|
@ -3,15 +3,11 @@
|
|||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <math.h>
|
||||
#include <complex.h>
|
||||
#include <alsa/asoundlib.h>
|
||||
#include <time.h>
|
||||
#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);
|
||||
|
|
|
|||
103
encode.c
103
encode.c
|
|
@ -3,14 +3,10 @@
|
|||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <math.h>
|
||||
#include <complex.h>
|
||||
#include <limits.h>
|
||||
#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));
|
||||
|
||||
|
|
|
|||
100
mmap_file.c
Normal file
100
mmap_file.c
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
6
mmap_file.h
Normal file
6
mmap_file.h
Normal file
|
|
@ -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
|
||||
43
pcm.c
Normal file
43
pcm.c
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
21
pcm.h
Normal file
21
pcm.h
Normal file
|
|
@ -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
|
||||
|
||||
108
wav.c
Normal file
108
wav.c
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
Loading…
Reference in a new issue