#include <u.h>#include <libc.h>#include <bio.h>#define MINIMP3_IMPLEMENTATION#define MINIMP3_NO_STDIO#include "minimp3_ex.h" static int noseek;static uvlong curpos;static Biobufhdr in;static uchar inb[MINIMP3_BUF_SIZE]; static size_treadcb(void *buf, size_t size, void *){ int n; return (n = Bread(&in, buf, size)) > 0 ? n : 0;} static intseekcb(uint64_t position, void *){ int n; if(noseek){ if(curpos > position) return -1; for(; position > 0; position -= n, curpos += n){ if((n = Bread(&in, inb, MINIMP3_MIN(position, sizeof(inb)))) < 0) return 0; } }else curpos = Bseek(&in, position, 0); return 0;} static voidusage(void){ fprint(2, "usage: %s [ -s SECONDS ]\n", argv0); exits("usage");} static mp3dec_ex_t dec;static mp3dec_io_t io = { .read = readcb, .seek = seekcb,};static mp3d_sample_t buf[2*4410]; voidmain(int argc, char **argv){ size_t n; double seekto; int out, pfd[2], pid; char fmt[32]; seekto = 0.0; ARGBEGIN{ case 's': seekto = atof(EARGF(usage())); break; default: usage(); }ARGEND if(Binits(&in, 0, OREAD, inb, sizeof(inb)) != 0) sysfatal("Binits"); noseek = Bseek(&in, 0, 2) < 0; if(!noseek) Bseek(&in, 0, 0); if(mp3dec_ex_open_cb(&dec, &io, MP3D_SEEK_TO_SAMPLE|MP3D_DO_NOT_SCAN) != 0) sysfatal("mp3dec_ex_open_cb"); if(seekto != 0.0) fprint(2, "time: %g\n", (noseek || mp3dec_ex_seek(&dec, seekto*dec.info.channels*dec.info.hz) != 0) ? 0.0 : seekto); out = 1; if((dec.info.channels != 2 || dec.info.hz != 44100)){ pid = -1; if(pipe(pfd) < 0 || (pid = fork()) < 0) sysfatal("%r"); if(pid == 0){ dup(pfd[1], 0); close(pfd[1]); close(pfd[0]); snprint(fmt, sizeof(fmt), "s16c%dr%d", dec.info.channels, dec.info.hz); execl("/bin/audio/pcmconv", "pcmconv", "-i", fmt, nil); sysfatal("%r"); } close(1); close(pfd[1]); out = pfd[0]; } while((n = mp3dec_ex_read(&dec, buf, nelem(buf))) > 0) write(out, buf, n*sizeof(buf[0])); Bterm(&in); close(out); mp3dec_ex_close(&dec); waitpid(); exits(nil);}
#include <u.h>
#include <libc.h>
#include <bio.h>
#define MINIMP3_IMPLEMENTATION
#define MINIMP3_NO_STDIO
#include "minimp3_ex.h"
static int noseek;
static uvlong curpos;
static Biobufhdr in;
static uchar inb[MINIMP3_BUF_SIZE];
static size_t
readcb(void *buf, size_t size, void *)
{
int n;
return (n = Bread(&in, buf, size)) > 0 ? n : 0;
}
static int
seekcb(uint64_t position, void *)
{
int n;
if(noseek){
if(curpos > position)
return -1;
for(; position > 0; position -= n, curpos += n){
if((n = Bread(&in, inb, MINIMP3_MIN(position, sizeof(inb)))) < 0)
return 0;
}
}else
curpos = Bseek(&in, position, 0);
return 0;
}
static void
usage(void)
{
fprint(2, "usage: %s [ -s SECONDS ]\n", argv0);
exits("usage");
}
static mp3dec_ex_t dec;
static mp3dec_io_t io = {
.read = readcb,
.seek = seekcb,
};
static mp3d_sample_t buf[2*4410];
void
main(int argc, char **argv)
{
size_t n;
double seekto;
int out, pfd[2], pid;
char fmt[32];
seekto = 0.0;
ARGBEGIN{
case 's':
seekto = atof(EARGF(usage()));
break;
default:
usage();
}ARGEND
if(Binits(&in, 0, OREAD, inb, sizeof(inb)) != 0)
sysfatal("Binits");
noseek = Bseek(&in, 0, 2) < 0;
if(!noseek)
Bseek(&in, 0, 0);
if(mp3dec_ex_open_cb(&dec, &io, MP3D_SEEK_TO_SAMPLE|MP3D_DO_NOT_SCAN) != 0)
sysfatal("mp3dec_ex_open_cb");
if(seekto != 0.0)
fprint(2, "time: %g\n", (noseek || mp3dec_ex_seek(&dec, seekto*dec.info.channels*dec.info.hz) != 0) ? 0.0 : seekto);
out = 1;
if((dec.info.channels != 2 || dec.info.hz != 44100)){
pid = -1;
if(pipe(pfd) < 0 || (pid = fork()) < 0)
sysfatal("%r");
if(pid == 0){
dup(pfd[1], 0);
close(pfd[1]);
close(pfd[0]);
snprint(fmt, sizeof(fmt), "s16c%dr%d", dec.info.channels, dec.info.hz);
execl("/bin/audio/pcmconv", "pcmconv", "-i", fmt, nil);
sysfatal("%r");
}
close(1);
close(pfd[1]);
out = pfd[0];
}
while((n = mp3dec_ex_read(&dec, buf, nelem(buf))) > 0)
write(out, buf, n*sizeof(buf[0]));
Bterm(&in);
close(out);
mp3dec_ex_close(&dec);
waitpid();
exits(nil);
}