1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
#include <u.h>
#include <libc.h>
typedef struct Wave Wave;
struct Wave
{
int rate;
int channels;
int framesz;
int bits;
int fmt;
};
ulong
get2(void)
{
uchar buf[2];
if(readn(0, buf, 2) != 2)
sysfatal("read: %r");
return buf[0] | buf[1]<<8;
}
ulong
get4(void)
{
uchar buf[4];
if(readn(0, buf, 4) != 4)
sysfatal("read: %r");
return buf[0] | buf[1]<<8 | buf[2]<<16 | buf[3]<<24;
}
char*
getcc(char tag[4])
{
if(readn(0, tag, 4) != 4)
sysfatal("read: %r");
return tag;
}
void
main(int, char *argv[])
{
char buf[1024], fmt[32];
ulong len, n;
Wave wav;
argv0 = argv[0];
if(memcmp(getcc(buf), "RIFF", 4) != 0)
sysfatal("no riff format");
get4();
if(memcmp(getcc(buf), "WAVE", 4) != 0)
sysfatal("not a wave file");
for(;;){
getcc(buf);
len = get4();
if(memcmp(buf, "data", 4) == 0)
break;
if(memcmp(buf, "fmt ", 4) == 0){
if(len < 2+2+4+4+2+2)
sysfatal("format chunk too small");
wav.fmt = get2();
wav.channels = get2();
wav.rate = get4();
get4();
wav.framesz = get2();
wav.bits = get2();
len -= 2+2+4+4+2+2;
}
while(len > 0){
n = sizeof(buf);
if(len < n)
n = len;
n = read(0, buf, n);
if(n <= 0)
sysfatal("read: %r");
len -= n;
}
}
switch(wav.fmt){
case 1:
snprint(fmt, sizeof(fmt), "%c%dr%dc%d", wav.bits == 8 ? 'u' : 's',
wav.bits, wav.rate, wav.channels);
break;
case 3:
snprint(fmt, sizeof(fmt), "f32r%dc%d", wav.rate, wav.channels);
break;
case 6:
snprint(fmt, sizeof(fmt), "a8r%dc%d", wav.rate, wav.channels);
break;
case 7:
snprint(fmt, sizeof(fmt), "µ8r%dc%d", wav.rate, wav.channels);
break;
default:
sysfatal("wave format (0x%lux) not supported", (ulong)wav.fmt);
}
snprint(buf, sizeof(buf), "%lud", len);
execl("/bin/audio/pcmconv", "pcmconv", "-i", fmt, "-l", buf, nil);
}
|