CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
orangepi-xunlong

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: orangepi-xunlong/orangepi-build
Path: blob/next/external/cache/sources/tinyalsa_hub/tinycap_hub.c
Views: 3959
1
/* tinycap.c
2
**
3
** Copyright 2011, The Android Open Source Project
4
**
5
** Redistribution and use in source and binary forms, with or without
6
** modification, are permitted provided that the following conditions are met:
7
** * Redistributions of source code must retain the above copyright
8
** notice, this list of conditions and the following disclaimer.
9
** * Redistributions in binary form must reproduce the above copyright
10
** notice, this list of conditions and the following disclaimer in the
11
** documentation and/or other materials provided with the distribution.
12
** * Neither the name of The Android Open Source Project nor the names of
13
** its contributors may be used to endorse or promote products derived
14
** from this software without specific prior written permission.
15
**
16
** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND
17
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE
20
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26
** DAMAGE.
27
*/
28
29
#include <tinyalsa/asoundlib.h>
30
#include <stdio.h>
31
#include <stdlib.h>
32
#include <stdint.h>
33
#include <signal.h>
34
#include <string.h>
35
36
#define ID_RIFF 0x46464952
37
#define ID_WAVE 0x45564157
38
#define ID_FMT 0x20746d66
39
#define ID_DATA 0x61746164
40
41
#define FORMAT_PCM 1
42
43
struct wav_header {
44
uint32_t riff_id;
45
uint32_t riff_sz;
46
uint32_t riff_fmt;
47
uint32_t fmt_id;
48
uint32_t fmt_sz;
49
uint16_t audio_format;
50
uint16_t num_channels;
51
uint32_t sample_rate;
52
uint32_t byte_rate;
53
uint16_t block_align;
54
uint16_t bits_per_sample;
55
uint32_t data_id;
56
uint32_t data_sz;
57
};
58
59
int loop_seconds = 0;
60
int capturing = 1;
61
int prinfo = 1;
62
63
unsigned int capture_sample(FILE *file, unsigned int card, unsigned int device,
64
unsigned int channels, unsigned int rate,
65
enum pcm_format format, unsigned int period_size,
66
unsigned int period_count);
67
68
void sigint_handler(int sig)
69
{
70
capturing = 0;
71
}
72
73
int main(int argc, char **argv)
74
{
75
FILE *file;
76
struct wav_header header;
77
unsigned int card = 0;
78
unsigned int device = 0;
79
unsigned int channels = 2;
80
unsigned int rate = 44100;
81
unsigned int bits = 16;
82
unsigned int frames;
83
unsigned int period_size = 1024;
84
unsigned int period_count = 4;
85
enum pcm_format format;
86
int no_header = 0;
87
88
if (argc < 2) {
89
fprintf(stderr, "Usage: %s {file.wav | --} [-D card] [-d device] [-c channels] "
90
"[-t seconds] [-r rate] [-b bits] [-p period_size] [-n n_periods]\n\n"
91
"Use -- for filename to send raw PCM to stdout\n", argv[0]);
92
return 1;
93
}
94
95
if (strcmp(argv[1],"--") == 0) {
96
file = stdout;
97
prinfo = 0;
98
no_header = 1;
99
} else {
100
file = fopen(argv[1], "wb");
101
if (!file) {
102
fprintf(stderr, "Unable to create file '%s'\n", argv[1]);
103
return 1;
104
}
105
}
106
107
/* parse command line arguments */
108
argv += 2;
109
while (*argv) {
110
if (strcmp(*argv, "-d") == 0) {
111
argv++;
112
if (*argv)
113
device = atoi(*argv);
114
} else if (strcmp(*argv, "-c") == 0) {
115
argv++;
116
if (*argv)
117
channels = atoi(*argv);
118
} else if (strcmp(*argv, "-r") == 0) {
119
argv++;
120
if (*argv)
121
rate = atoi(*argv);
122
} else if (strcmp(*argv, "-b") == 0) {
123
argv++;
124
if (*argv)
125
bits = atoi(*argv);
126
} else if (strcmp(*argv, "-D") == 0) {
127
argv++;
128
if (*argv)
129
card = atoi(*argv);
130
} else if (strcmp(*argv, "-p") == 0) {
131
argv++;
132
if (*argv)
133
period_size = atoi(*argv);
134
} else if (strcmp(*argv, "-n") == 0) {
135
argv++;
136
if (*argv)
137
period_count = atoi(*argv);
138
} else if (strcmp(*argv, "-t") == 0) {
139
argv++;
140
if (*argv)
141
loop_seconds = atoi(*argv);
142
}
143
if (*argv)
144
argv++;
145
}
146
147
header.riff_id = ID_RIFF;
148
header.riff_sz = 0;
149
header.riff_fmt = ID_WAVE;
150
header.fmt_id = ID_FMT;
151
header.fmt_sz = 16;
152
header.audio_format = FORMAT_PCM;
153
header.num_channels = channels;
154
header.sample_rate = rate;
155
156
switch (bits) {
157
case 32:
158
format = PCM_FORMAT_S32_LE;
159
break;
160
case 24:
161
format = PCM_FORMAT_S24_LE;
162
break;
163
case 16:
164
format = PCM_FORMAT_S16_LE;
165
break;
166
default:
167
fprintf(stderr, "%d bits is not supported.\n", bits);
168
return 1;
169
}
170
171
header.bits_per_sample = pcm_format_to_bits(format);
172
header.byte_rate = (header.bits_per_sample / 8) * channels * rate;
173
header.block_align = channels * (header.bits_per_sample / 8);
174
header.data_id = ID_DATA;
175
176
/* leave enough room for header */
177
if (!no_header) {
178
fseek(file, sizeof(struct wav_header), SEEK_SET);
179
}
180
181
/* install signal handler and begin capturing */
182
signal(SIGINT, sigint_handler);
183
frames = capture_sample(file, card, device, header.num_channels,
184
header.sample_rate, format,
185
period_size, period_count);
186
if (prinfo) {
187
printf("Captured %d frames\n", frames);
188
}
189
190
/* write header now all information is known */
191
if (!no_header) {
192
header.data_sz = frames * header.block_align;
193
header.riff_sz = header.data_sz + sizeof(header) - 8;
194
fseek(file, 0, SEEK_SET);
195
fwrite(&header, sizeof(struct wav_header), 1, file);
196
}
197
198
fclose(file);
199
200
return 0;
201
}
202
203
unsigned int capture_sample(FILE *file, unsigned int card, unsigned int device,
204
unsigned int channels, unsigned int rate,
205
enum pcm_format format, unsigned int period_size,
206
unsigned int period_count)
207
{
208
struct pcm_config config;
209
struct pcm *pcm;
210
struct pcm *pcm1;
211
char *buffer;
212
unsigned int size;
213
unsigned int frames;
214
unsigned long long bytes_read = 0;
215
struct timeval tv;
216
struct timezone tz;
217
long time_sec1;
218
long time_sec2;
219
long time_total;
220
221
config.channels = channels;
222
config.rate = rate;
223
config.period_size = period_size;
224
config.period_count = period_count;
225
config.format = format;
226
config.start_threshold = 0;
227
config.stop_threshold = 0;
228
config.silence_threshold = 0;
229
230
pcm = pcm_open(card, device, PCM_IN, &config);
231
if (!pcm || !pcm_is_ready(pcm)) {
232
fprintf(stderr, "Unable to open PCM device (%s)\n",
233
pcm_get_error(pcm));
234
return 0;
235
}
236
237
if (device == 0)
238
pcm1 = pcm_open(2, 0, PCM_IN, &config);
239
else
240
printf("error: device is error");
241
if (!pcm1 || !pcm_is_ready(pcm1)) {
242
fprintf(stderr, "Unable to open PCM device %u (%s)\n",
243
device, pcm_get_error(pcm1));
244
return 0;
245
}
246
247
pcm_prepare(pcm);
248
pcm_prepare(pcm1);
249
250
size = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm));
251
buffer = malloc(size);
252
if (!buffer) {
253
fprintf(stderr, "Unable to allocate %d bytes\n", size);
254
free(buffer);
255
pcm_close(pcm);
256
pcm_close(pcm1);
257
return 0;
258
}
259
260
if (prinfo) {
261
printf("Capturing sample: %u ch, %u hz, %u bit\n", channels, rate,
262
pcm_format_to_bits(format));
263
}
264
265
gettimeofday(&tv, &tz);
266
time_sec1 = tv.tv_sec;
267
while (capturing && !pcm_read(pcm, buffer, size)) {
268
if (fwrite(buffer, 1, size, file) != size) {
269
fprintf(stderr,"Error capturing sample\n");
270
break;
271
}
272
gettimeofday(&tv, &tz);
273
time_sec2 = tv.tv_sec;
274
time_total = time_sec2 - time_sec1;
275
if (time_total >= (loop_seconds)) {
276
printf("time_total:%ld, loop_seconds:%d\n",
277
time_total, loop_seconds);
278
break;
279
}
280
bytes_read += size;
281
}
282
frames = pcm_bytes_to_frames(pcm, bytes_read);
283
free(buffer);
284
pcm_close(pcm);
285
pcm_close(pcm1);
286
return frames;
287
}
288
289
290