-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdevox.c
221 lines (206 loc) · 6.01 KB
/
devox.c
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
/* Filename: devox.c
Description: Kind of like the program sox. It converts voice
file formats. Converts
the Dialogic or Oki ADPCM (foo.vox or foo.32K) file format
to 16 bit and 8 bit raw voice files.
Usage: devox [-b 8|-b 16] infile outfile
The -b is for 8 or 16 bit files (reference to input files)
Default is 8 bits.
*/
#include <unistd.h> /* needed for getopt */
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "adpcm.h"
void write12(int, int, short *, int ); /* program to write and convert
* data to 12 bit format.
*/
int
main (int argc, char **argv)
{
int c, i, j;
extern char *optarg;
extern int optind;
int infile, outfile, n;
int buffer_size, sample_size;
short *buffer12;
char *adpcm;
struct adpcm_status coder_stat;
/*
* Process the arguments.
*/
sample_size = 1; /* default to 8 bit */
while ((c = getopt(argc, argv, "b:")) != -1) {
switch (c) {
case 'b':
/*
* set bits per sample to 8 or 16 - sample_size to
* 1 or 2 bytes.
*/
switch (atoi(optarg)) {
case 8:
sample_size = 1;
break;
case 16:
sample_size = 2;
break;
default:
fprintf(stderr, "Wrong bit specification, 8 bit/sample used.\n");
sample_size = 1;
break;
}
break;
default:
/*
* set bits per sample to 8 - sample_size to 1 byte.
*/
sample_size = 1;
break;
}
}
/*
* Process extra arguments. (infile outfile)
*/
if (argc - optind != 2) {
fprintf( stderr, "%s: USAGE: devox [-b 8|-b 16] infile outfile\n",
argv[0]);
exit(1);
}
/*
* Open the input file for reading.
*/
if ((infile = open(argv[optind], O_RDONLY)) < 0) {
perror(argv[optind]);
exit(1);
}
/*
* Open the output file for writing.
*/
if ((outfile = open(argv[++optind], O_WRONLY | O_CREAT, 0666)) < 0) {
perror(argv[optind]);
exit(1);
}
/*
* convert the 12 bit samples linear to the final format of either
* 8 or 16 bit and write the output file.
*/
/*
* Allocate memory for the buffer of 12 bit data.
*/
buffer_size = 1024;
buffer12=(short*) calloc (buffer_size,sizeof(short));
/* Check that memory was allocated correctly */
if (buffer12==NULL) {
fprintf (stderr,"%s: Malloc Error",argv[0] );
exit(1);
}
/*
* Initialize the coder.
*/
adpcm_init( &coder_stat );
/*
* Allocate memory for the buffer of ADPCM samples.
*/
adpcm=(char*) calloc (buffer_size/2,sizeof(char));
/* Check that memory was allocated correctly */
if (adpcm==NULL) {
fprintf (stderr,"%s: Malloc Error",argv[0] );
exit(1);
}
/*
* Read the data; continue until end of file
*/
while ((n=read(infile, adpcm, buffer_size*sizeof(char)/2))>0 ) {
/*
* Convert data to linear format
* Note that two ADPCM samples are stored in (8 bit) char,
* because the ADPCM samples are only 4 bits.
*/
j = 0;
for(i=0; i<n; i++) {
buffer12[j++] = adpcm_decode( (adpcm[i]>>4)&0x0f, &coder_stat );
buffer12[j++] = adpcm_decode( adpcm[i]&0x0f, &coder_stat );
}
/*
* now convert from 12 bit to either 8 or 16 and write the output file.
*/
write12(outfile, sample_size, buffer12, n*2);
}
/*
* free allocated memory
*/
free( buffer12 );
free( adpcm );
/*
* Close the input and output files
*/
close(infile);
close(outfile);
exit(0);
}
/*
* program to convert data from 12 bit format and write it.
*/
void write12(int outfile,int sample_size, short *buffer12,int buffer_size)
{
int i;
unsigned char *buffer8;
/*
* The 8 bit case first.
* The second bit of sample_size indicates whether 8 or 16 bit, hence the
* bitwise operation in the condition.
*/
if (!(sample_size>>1)) {
/*
* Allocate memory for the buffer.
*/
buffer8=(unsigned char*) calloc (buffer_size,sizeof(unsigned char));
/* Check that memory was allocated correctly */
if (buffer8==NULL) {
fprintf (stderr,"Malloc Error" );
exit(1);
}
/*
* Convert the 12 bit samples to 8 bit
* Need to add 128 because it is a unsigned char.
*/
for (i=0; i<buffer_size; i++) {
//buffer12[i] /= 16;
buffer12[i] /= 32;
buffer8[i] = (char)(buffer12[i] + 128);
}
/*
* Write the next block of data;
*/
if (write(outfile,buffer8,buffer_size*sizeof(char))<0 ) {
fprintf (stderr,"Error in writing file.");
exit(1);
}
free( buffer8 );
}
else { /* now write the 16 bit data */
/*
* Convert the 12 bit samples to 16 bit.
*/
for (i=0; i<buffer_size; i++) {
buffer12[i] *= 16;
// Compiler should implement at a shift left 4 bits.
// The following was a temporary work around for a
// clipping problem. -- believed to be fixed in version
// 1.1 (see web page and adpcm.c line 99). TLB 3/30/04
//buffer12[i] *= 8;
}
/*
* write the next block of data;
* Can use the 12-bit buffer for the 16 bit data.
*/
if (write(outfile,buffer12,buffer_size*sizeof(short))<0 ) {
fprintf (stderr,"Error in writing file.");
exit(1);
}
}
return;
}