aboutsummaryrefslogtreecommitdiff
path: root/mixer.c
diff options
context:
space:
mode:
authorrodri <rgl@antares-labs.eu>2023-10-02 12:54:17 +0000
committerrodri <rgl@antares-labs.eu>2023-10-02 12:54:17 +0000
commitd79098840557bb4687a2e6640728dd69c62bf3a3 (patch)
treee71de17179729a59f0cc6dc6703040212a5f180a /mixer.c
parent6389f8dbca36ddc1ca4028fdb404d63eb404357f (diff)
downloadbattleship-d79098840557bb4687a2e6640728dd69c62bf3a3.tar.gz
battleship-d79098840557bb4687a2e6640728dd69c62bf3a3.tar.bz2
battleship-d79098840557bb4687a2e6640728dd69c62bf3a3.zip
replaced the custom wav decoder for the general Pcm one using the audio(1) ones.
Diffstat (limited to 'mixer.c')
-rw-r--r--mixer.c365
1 files changed, 90 insertions, 275 deletions
diff --git a/mixer.c b/mixer.c
index d2eb2a9..2145fc3 100644
--- a/mixer.c
+++ b/mixer.c
@@ -3,14 +3,13 @@
*/
#include <u.h>
#include <libc.h>
-#include <bio.h>
#include <thread.h>
#include "mixer.h"
static Mixer mixer;
-static int wav_init(AudioSourceInfo*, void*, int, int);
+static int wav_init(AudioSourceInfo*, int);
static int mp3_init(AudioSourceInfo*, int);
static int
@@ -250,90 +249,11 @@ audio_new_source(AudioSourceInfo *info)
return src;
}
-static int
-check_header(void *data, int size, char *str, int offset)
-{
- int len;
-
- len = strlen(str);
- return size >= offset + len &&
- memcmp((char*)data + offset, str, len) == 0;
-}
-
-static AudioSource *
-new_source_from_mem(void *data, int size, int ownsdata)
-{
- AudioSourceInfo info;
-
- if(check_header(data, size, "WAVE", 8)){
- if(wav_init(&info, data, size, ownsdata) < 0)
- return nil;
- return audio_new_source(&info);
- }
-
- werrstr("unknown format or invalid data");
- return nil;
-}
-
-static void *
-load_file(char *filename, int *size)
-{
- Biobuf *fp;
- void *data;
- int n;
-
- fp = Bopen(filename, OREAD);
- if(fp == nil)
- return nil;
-
- Bseek(fp, 0, 2);
- *size = Boffset(fp);
- Bseek(fp, 0, 0);
-
- data = malloc(*size);
- if(data == nil){
- Bterm(fp);
- return nil;
- }
- n = Bread(fp, data, *size);
- Bterm(fp);
- if(n != *size){
- free(data);
- return nil;
- }
-
- return data;
-}
-
-AudioSource *
-audio_new_source_from_file(char *filename)
-{
- int size;
- AudioSource *src;
- void *data;
-
- /* Load file into memory */
- data = load_file(filename, &size);
- if(data == nil){
- werrstr("could not load file");
- return nil;
- }
-
- /* Try to load and return */
- src = new_source_from_mem(data, size, 1);
- if(src == nil){
- free(data);
- return nil;
- }
-
- return src;
-}
-
AudioSource *
-audio_new_source_from_mp3file(char *path)
+audio_new_source_from_file(char *path)
{
AudioSourceInfo info;
- uchar buf[3];
+ uchar buf[12];
int fd;
fd = open(path, OREAD);
@@ -343,13 +263,18 @@ audio_new_source_from_mp3file(char *path)
memset(buf, 0, sizeof buf);
readn(fd, buf, sizeof buf);
seek(fd, 0, 0);
- if(memcmp(buf, "ID3", 3) != 0 && (buf[0] != 0xFF || buf[1] != 0xFB)){
- werrstr("bad mp3 file");
- close(fd);
- return nil;
- }
-
- if(mp3_init(&info, fd) < 0){
+ if(memcmp(buf, "ID3", 3) == 0 || (buf[0] == 0xFF && buf[1] == 0xFB)){
+ if(mp3_init(&info, fd) < 0){
+ close(fd);
+ return nil;
+ }
+ }else if(memcmp(buf+8, "WAVE", 4) == 0){
+ if(wav_init(&info, fd) < 0){
+ close(fd);
+ return nil;
+ }
+ }else{
+ werrstr("unsupported file format");
close(fd);
return nil;
}
@@ -358,12 +283,6 @@ audio_new_source_from_mp3file(char *path)
return audio_new_source(&info);
}
-AudioSource *
-audio_new_source_from_mem(void *data, int size)
-{
- return new_source_from_mem(data, size, 0);
-}
-
void
audio_destroy_source(AudioSource *src)
{
@@ -472,184 +391,6 @@ audio_stop(AudioSource *src)
src->rewind = 1;
}
-/*
- * Wav stream processing
- */
-
-static char *
-find_subchunk(char *data, int len, char *id, int *size)
-{
- /* TODO : Error handling on malformed wav file */
- int idlen;
- char *p;
-
- idlen = strlen(id);
- p = data+12;
-next:
- *size = *((u32int*)(p+4));
- if(memcmp(p, id, idlen) != 0){
- p += 8 + *size;
- if(p > data + len)
- return nil;
- goto next;
- }
- return p+8;
-}
-
-static int
-read_wav(Wav *w, void *data, int len)
-{
- uint format, channels, samplerate, bitdepth;
- int sz;
- char *p;
-
- p = data;
- memset(w, 0, sizeof(*w));
-
- /* Check header */
- if(memcmp(p, "RIFF", 4) != 0 || memcmp(p+8, "WAVE", 4) != 0){
- werrstr("bad wav header");
- return -1;
- }
-
- /* Find fmt subchunk */
- p = find_subchunk(data, len, "fmt", &sz);
- if(p == nil){
- werrstr("no fmt subchunk");
- return -1;
- }
-
- /* Load fmt info */
- format = *((u16int*)(p));
- channels = *((u16int*)(p+2));
- samplerate = *((u32int*)(p+4));
- bitdepth = *((u16int*)(p+14));
-
- if(format != 1){
- werrstr("unsupported format");
- return -1;
- }
- if(channels == 0 || samplerate == 0 || bitdepth == 0){
- werrstr("bad format");
- return -1;
- }
- if(channels > 2 || (bitdepth != 16 && bitdepth != 8)){
- werrstr("unsupported wav format");
- return -1;
- }
-
- /* Find data subchunk */
- p = find_subchunk(data, len, "data", &sz);
- if(p == nil){
- werrstr("no data subchunk");
- return -1;
- }
-
- /* Init struct */
- w->data = (void*)p;
- w->samplerate = samplerate;
- w->channels = channels;
- w->length = (sz / (bitdepth/8)) / channels;
- w->bitdepth = bitdepth;
- return 0;
-}
-
-static void
-wav_handler(AudioEvent *e)
-{
- int x, n;
- s16int *dst;
- WavStream *s;
- int len;
-
- s = e->udata;
-
- switch(e->type){
- case AUDIO_EVENT_DESTROY:
- free(s->data);
- free(s);
- break;
- case AUDIO_EVENT_SAMPLES:
- dst = e->buffer;
- len = e->length/2;
-fill:
- n = min(len, s->wav.length - s->idx);
- len -= n;
- switch(s->wav.bitdepth){
- case 16:
- if(s->wav.channels == 1){
- while(n--){
- dst[0] = dst[1] = ((s16int*)s->wav.data)[s->idx];
- dst += 2;
- s->idx++;
- }
- }else if(s->wav.channels == 2){
- while(n--){
- x = s->idx * 2;
- dst[0] = ((s16int*)s->wav.data)[x];
- dst[1] = ((s16int*)s->wav.data)[x+1];
- dst += 2;
- s->idx++;
- }
- }
- break;
- case 8:
- if(s->wav.channels == 1){
- while(n--){
- dst[0] = dst[1] = (((uchar*)s->wav.data)[s->idx] - 128) << 8;
- dst += 2;
- s->idx++;
- }
- }else if(s->wav.channels == 2){
- while(n--){
- x = s->idx * 2;
- dst[0] = (((uchar*)s->wav.data)[x] - 128) << 8;
- dst[1] = (((uchar*)s->wav.data)[x+1] - 128) << 8;
- dst += 2;
- s->idx++;
- }
- }
- break;
- }
- /* Loop back and continue filling buffer if we didn't fill the buffer */
- if(len > 0){
- s->idx = 0;
- goto fill;
- }
- break;
- case AUDIO_EVENT_REWIND:
- s->idx = 0;
- break;
- }
-}
-
-static int
-wav_init(AudioSourceInfo *info, void *data, int len, int ownsdata)
-{
- WavStream *stream;
-
- stream = malloc(sizeof *stream);
- if(stream == nil){
- werrstr("allocation failed");
- return -1;
- }
- memset(stream, 0, sizeof *stream);
-
- if(read_wav(&stream->wav, data, len) < 0)
- return -1;
-
- if(ownsdata)
- stream->data = data;
- stream->idx = 0;
-
- info->udata = stream;
- info->handler = wav_handler;
- info->samplerate = stream->wav.samplerate;
- info->length = stream->wav.length;
-
- return 0;
-}
-
static void
pcm_handler(AudioEvent *e)
{
@@ -671,7 +412,7 @@ Fillbuf:
n = min(len, pcm->len - pcm->off);
len -= n;
while(n--){
- i = pcm->off * 2;
+ i = 2*pcm->off;
dst[0] = ((s16int*)pcm->data)[i];
dst[1] = ((s16int*)pcm->data)[i+1];
dst += 2;
@@ -760,3 +501,77 @@ mp3_init(AudioSourceInfo *info, int fd)
return 0;
}
+
+/* TODO generalize the *decproc and *_init procedures */
+static void
+wavdecproc(void *arg)
+{
+ int *pfd, fd;
+
+ pfd = arg;
+ fd = pfd[2];
+
+ close(pfd[0]);
+ dup(fd, 0);
+ close(fd);
+ dup(pfd[1], 1);
+ close(pfd[1]);
+
+ execl("/bin/audio/wavdec", "wavdec", nil);
+ threadexitsall("execl: %r");
+}
+
+static int
+wav_init(AudioSourceInfo *info, int fd)
+{
+ Pcm *pcm;
+ void *data;
+ uchar buf[1024];
+ int pfd[3], n, len;
+
+ data = nil;
+ len = 0;
+
+ if(pipe(pfd) < 0){
+ werrstr("pipe: %r");
+ return -1;
+ }
+ pfd[2] = fd;
+
+ procrfork(wavdecproc, pfd, mainstacksize, RFFDG|RFNAMEG|RFNOTEG);
+ close(pfd[1]);
+ while((n = read(pfd[0], buf, sizeof buf)) > 0){
+ data = realloc(data, len+n);
+ if(data == nil){
+ werrstr("realloc: %r");
+ return -1;
+ }
+ memmove((uchar*)data+len, buf, n);
+ len += n;
+ }
+ close(pfd[0]);
+
+ pcm = malloc(sizeof *pcm);
+ if(pcm == nil){
+ free(data);
+ werrstr("malloc: %r");
+ return -1;
+ }
+ pcm->depth = 16;
+ pcm->chans = 2;
+ pcm->rate = 44100;
+ pcm->data = data;
+ pcm->len = len/(pcm->depth/8)/pcm->chans;
+
+ info->udata = pcm;
+ info->handler = pcm_handler;
+ info->samplerate = pcm->rate;
+ info->length = pcm->len;
+
+// fprint(2, "pcm 0x%p:\ndata 0x%p\nlen %d\ndepth %d\nchans %d\nrate %d\n",
+// pcm, pcm->data, pcm->len, pcm->depth, pcm->chans, pcm->rate);
+// fprint(2, "info 0x%p:\nudata 0x%p\nhandler 0x%p\nsamplerate %d\nlength %d\n",
+// info, info->udata, info->handler, info->samplerate, info->length);
+
+ return 0;
+}