blob: f2e104c01454dc979186acc36425efae7acf7615 [file] [log] [blame]
b.liu1c1c7212023-12-22 16:35:27 +08001#include <sys/stat.h>
2#include <unistd.h>
3#include <stdio.h>
4#include <fcntl.h>
5#include <errno.h>
6
7#include "mbtk_log.h"
8#include "mbtk_audio_internal.h"
9
10#define WAV_PLAY_BUFF 2048
11
b.liub21bd8d2023-12-28 19:07:21 +080012typedef struct {
13 const unsigned char *pcm_data;
14 int data_size;
15} audio_buff_t;
16
b.liu1c1c7212023-12-22 16:35:27 +080017static int wav_play_fd = -1;
18static audio_play_state_enum play_state = AUDIO_PLAY_STATE_STOP;
19static pthread_cond_t play_cond;
20static pthread_mutex_t play_mutex;
21static pthread_t play_thread_play;
22
23static int wav_recorder_fd = -1;
24static struct wav_header recorder_header;
25static uint32 recorver_data_count = 0;
26
b.liub21bd8d2023-12-28 19:07:21 +080027static audio_buff_t audio_buff;
28
b.liu1c1c7212023-12-22 16:35:27 +080029static void audio_play_thread(void *arg)
30{
31 int rc, len, frames = 0;
32 char buf[WAV_PLAY_BUFF];
33
34 play_state = AUDIO_PLAY_STATE_RUNNING;
35 pthread_mutex_init(&play_mutex, NULL);
36 pthread_cond_init(&play_cond, NULL);
37
b.liub21bd8d2023-12-28 19:07:21 +080038 int data_send = 0;
b.liu1c1c7212023-12-22 16:35:27 +080039 while (TRUE) {
40 /* Playback loop */
41 pthread_mutex_lock(&play_mutex);
42 if(play_state == AUDIO_PLAY_STATE_STOP) {
43 LOGD("Stop play...");
44 pthread_mutex_unlock(&play_mutex);
45 break;
46 } else if(play_state == AUDIO_PLAY_STATE_PAUSE) {
47 pthread_cond_wait(&play_cond, &play_mutex);
48 pthread_mutex_unlock(&play_mutex);
49 continue;
50 } else {
51 pthread_mutex_unlock(&play_mutex);
52 }
53
54 memset(buf, 0x00, sizeof(buf));
b.liub21bd8d2023-12-28 19:07:21 +080055 if(wav_play_fd > 0) { // Play file.
56 len = read(wav_play_fd, buf, WAV_PLAY_BUFF);
57 if (len == -1) {
58 LOGE("%s: error reading from file", __FUNCTION__);
59 goto thread_end;
60 }
b.liu1c1c7212023-12-22 16:35:27 +080061
b.liub21bd8d2023-12-28 19:07:21 +080062 if (len == 0) {
63 /* reached EOF */
64 LOGE("%s: Read wav file end.", __FUNCTION__);
65 break;
66 }
67 } else { // Play buffer.
68 if(data_send >= audio_buff.data_size) {
69 /* reached EOF */
70 LOGE("%s: Read buffer end.", __FUNCTION__);
71 break;
72 }
73 if(audio_buff.data_size - data_send >= WAV_PLAY_BUFF) {
74 memcpy(buf, audio_buff.pcm_data + data_send, WAV_PLAY_BUFF);
75 len = WAV_PLAY_BUFF;
76 } else {
77 memcpy(buf, audio_buff.pcm_data + data_send, audio_buff.data_size - data_send);
78 len = audio_buff.data_size - data_send;
79 }
80 data_send += len;
b.liu1c1c7212023-12-22 16:35:27 +080081 }
82
83 if((rc = mbtk_audio_pcm_play_data_send(buf, len)) < len) {
84 LOGE("Send data %d/%d", rc, len);
85 goto thread_end;
86 }
87
88 LOGD("%s: No.%d frame playback", __FUNCTION__, ++frames);
89 }
90
91 play_state = AUDIO_PLAY_STATE_STOP;
92
93thread_end:
94 pthread_mutex_destroy(&play_mutex);
95 pthread_cond_destroy(&play_cond);
96 mbtk_audio_pcm_play_stop();
97
b.liub21bd8d2023-12-28 19:07:21 +080098 if(wav_play_fd > 0) {
99 if (close(wav_play_fd))
100 LOGE("%s: error closing file", __FUNCTION__);
101 }
b.liu1c1c7212023-12-22 16:35:27 +0800102
103 wav_play_fd = -1;
104 LOGD("%s: finished pcm playback.", __FUNCTION__);
105 return;
106}
107
108static void audio_recorder_cb(void *data, uint32 data_len)
109{
110 if(data_len > 0) {
111 LOGD("Recorver data:%d, count:%d", data_len, recorver_data_count);
112 if (write(wav_recorder_fd, data, data_len) < data_len) {
113 LOGE("%s: error writing to file!", __FUNCTION__);
114 }
115 recorver_data_count += data_len;
116 } else {
117 LOGD("Recorver data end.");
118 recorder_header.data_sz = recorver_data_count;
119 recorder_header.riff_sz = recorder_header.data_sz + sizeof(recorder_header) - 8;
120 lseek(wav_recorder_fd, 0, SEEK_SET);
121 write(wav_recorder_fd, &recorder_header, sizeof(struct wav_header));
122
123 close(wav_recorder_fd);
124 wav_recorder_fd = -1;
125 }
126}
127
128int mbtk_audio_wav_init()
129{
130 //mbtk_log_init("radio", "MBTK_AUDIO");
131 return mbtk_audio_pcm_init();
132}
133
134int mbtk_audio_wav_play_start(const void *wav_file)
135{
136 struct stat st;
137 const char *path = (const char *)wav_file;
138 struct riff_wave_header riff_wave_header;
139 struct chunk_header chunk_header;
140 struct chunk_fmt chunk_fmt = {0};
141 unsigned int more_chunks = 1;
142
143 if(play_state != AUDIO_PLAY_STATE_STOP) {
144 LOGW("Audio is playing...");
145 return -1;
146 }
147
148 /* Check and open source file */
149 if (access(path, F_OK) || stat(path, &st)) {
150 LOGE("%s: error reading from file %s", __FUNCTION__, path);
151 return -1;
152 }
153
154 if (!st.st_size) {
155 LOGE("%s: empty file %s", __FUNCTION__, path);
156 return -1;
157 }
158
159 wav_play_fd = open(path, O_RDONLY);
160 if (wav_play_fd < 0) {
161 LOGE("%s: error opening file %s", __FUNCTION__, path);
162 return -1;
163 }
164
165 read(wav_play_fd, &riff_wave_header, sizeof(riff_wave_header));
166 if ((riff_wave_header.riff_id != ID_RIFF) || (riff_wave_header.wave_id != ID_WAVE)) {
167 LOGE("Error: '%s' is not a riff/wave file", path);
168 close(wav_play_fd);
169 return -1;
170 }
171
172 do {
173 read(wav_play_fd, &chunk_header, sizeof(chunk_header));
174
175 switch (chunk_header.id) {
176 case ID_FMT:
177 read(wav_play_fd, &chunk_fmt, sizeof(chunk_fmt));
178 /* If the format header is larger, skip the rest */
179 if (chunk_header.sz > sizeof(chunk_fmt))
180 lseek(wav_play_fd, chunk_header.sz - sizeof(chunk_fmt), SEEK_CUR);
181 break;
182 case ID_DATA:
183 /* Stop looking for chunks */
184 more_chunks = 0;
185 break;
186 default:
187 /* Unknown chunk, skip bytes */
188 lseek(wav_play_fd, chunk_header.sz, SEEK_CUR);
189 }
190 } while (more_chunks);
191
192 //Support 8k/16k & mono wave file
193 if (((chunk_fmt.sample_rate != 8000) && (chunk_fmt.sample_rate != 16000))
194 || (chunk_fmt.num_channels != 1) ) {
195 LOGD("%s: error wave file:sample_rate = %d, num_channels = %d!!",
196 __FUNCTION__,chunk_fmt.sample_rate, chunk_fmt.num_channels);
197 close(wav_play_fd);
198 return -1;
199 }
200
201 LOGE("%s: success open wave file:%s, sample_rate = %d, num_channels = %d.",
202 __FUNCTION__, path, chunk_fmt.sample_rate, chunk_fmt.num_channels);
203
204 if ((8000 == chunk_fmt.sample_rate) && (1 == chunk_fmt.num_channels)) {
205 mbtk_audio_pcm_sample_rate_set(MBTK_AUDIO_SAMPLE_RATE_8000);
206 } else if ((16000 == chunk_fmt.sample_rate) && (1 == chunk_fmt.num_channels)) {
207 mbtk_audio_pcm_sample_rate_set(MBTK_AUDIO_SAMPLE_RATE_16000);
208 }
209
210 if (mbtk_audio_pcm_play_start()) {
211 LOGE("%s: error opening output device.", __FUNCTION__);
212 return -1;
213 }
214
215 LOGD("Start play wav file...");
216
217 pthread_attr_t thread_attr;
218 pthread_attr_init(&thread_attr);
219 if(pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED))
220 {
221 LOGE("pthread_attr_setdetachstate() fail.");
222 return -1;
223 }
224
225 if (pthread_create(&play_thread_play, NULL, (void *)&audio_play_thread, NULL) < 0) {
226 LOGE("%s: error creating thread_play!", __FUNCTION__);
227 return -1;
228 }
229
230 return 0;
231}
232
b.liub21bd8d2023-12-28 19:07:21 +0800233int mbtk_audio_wav_stream_play_start(const unsigned char *pcm_data, int data_size, int sample_rate, int num_channels)
234{
235 if(play_state != AUDIO_PLAY_STATE_STOP) {
236 LOGW("Audio is playing...");
237 return -1;
238 }
239
240 //Support 8k/16k & mono wave file
241 if (((sample_rate != 8000) && (sample_rate != 16000))
242 || (num_channels != 1) ) {
243 LOGD("%s: error wave file:sample_rate = %d, num_channels = %d!!",
244 __FUNCTION__,sample_rate, num_channels);
245 return -1;
246 }
247
248 LOGE("%s: success open wave stream, sample_rate = %d, num_channels = %d.",
249 __FUNCTION__, sample_rate, num_channels);
250
251 if ((8000 == sample_rate) && (1 == num_channels)) {
252 mbtk_audio_pcm_sample_rate_set(MBTK_AUDIO_SAMPLE_RATE_8000);
253 } else if ((16000 == sample_rate) && (1 == num_channels)) {
254 mbtk_audio_pcm_sample_rate_set(MBTK_AUDIO_SAMPLE_RATE_16000);
255 }
256
257 if (mbtk_audio_pcm_play_start()) {
258 LOGE("%s: error opening output device.", __FUNCTION__);
259 return -1;
260 }
261
262 audio_buff.pcm_data = pcm_data;
263 audio_buff.data_size = data_size;
264 LOGD("Start play wav stream...");
265
266 pthread_attr_t thread_attr;
267 pthread_attr_init(&thread_attr);
268 if(pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED))
269 {
270 LOGE("pthread_attr_setdetachstate() fail.");
271 return -1;
272 }
273
274 if (pthread_create(&play_thread_play, NULL, (void *)&audio_play_thread, NULL) < 0) {
275 LOGE("%s: error creating thread_play!", __FUNCTION__);
276 return -1;
277 }
278
279 return 0;
280}
281
282
b.liu1c1c7212023-12-22 16:35:27 +0800283int mbtk_audio_wav_play_pause()
284{
285 int result = 0;
286 pthread_mutex_lock(&play_mutex);
287 if(play_state == AUDIO_PLAY_STATE_RUNNING) {
288 play_state = AUDIO_PLAY_STATE_PAUSE;
289 } else {
b.liub21bd8d2023-12-28 19:07:21 +0800290 // result = -1;
b.liu1c1c7212023-12-22 16:35:27 +0800291 LOGW("Audio state : %d", play_state);
292 }
293 pthread_mutex_unlock(&play_mutex);
294 return result;
295}
296
297int mbtk_audio_wav_play_resume()
298{
299 int result = 0;
300 pthread_mutex_lock(&play_mutex);
301 if(play_state == AUDIO_PLAY_STATE_PAUSE) {
302 play_state = AUDIO_PLAY_STATE_RUNNING;
303 pthread_cond_signal(&play_cond);
304 } else {
b.liub21bd8d2023-12-28 19:07:21 +0800305 // result = -1;
b.liu1c1c7212023-12-22 16:35:27 +0800306 LOGW("Audio state : %d", play_state);
307 }
308 pthread_mutex_unlock(&play_mutex);
309 return result;
310}
311
312
313int mbtk_audio_wav_play_stop()
314{
315 int result = 0;
316 pthread_mutex_lock(&play_mutex);
317 if(play_state == AUDIO_PLAY_STATE_PAUSE || play_state == AUDIO_PLAY_STATE_RUNNING) {
318 if(play_state == AUDIO_PLAY_STATE_PAUSE) {
319 pthread_cond_signal(&play_cond);
320 }
321 play_state = AUDIO_PLAY_STATE_STOP;
322 pthread_mutex_unlock(&play_mutex);
323
324 LOGD("Waitting play thread exit...");
325 if (pthread_join(play_thread_play, NULL)) {
326 LOGE("error join thread_play!");
327 // abort();
328 }
329 LOGD("Play thread exit success.");
330 } else {
331 pthread_mutex_unlock(&play_mutex);
b.liub21bd8d2023-12-28 19:07:21 +0800332 // result = -1;
b.liu1c1c7212023-12-22 16:35:27 +0800333 LOGW("Audio state : %d", play_state);
334 }
335
336 return result;
337}
338
339int mbtk_audio_wav_recorder_start(const void *wav_file, mbtk_audio_sample_rate_enum sample_rate)
340{
341 int rc;
342 const char *path = (const char *)wav_file;
343
344 LOGD("wav_file is %s.", path);
345 if(wav_recorder_fd > 0) {
346 LOGW("Audio is recorder...");
347 }
348
349 memset(&recorder_header, 0x0, sizeof(struct wav_header));
350 recorder_header.riff_id = ID_RIFF;
351 recorder_header.riff_sz = 0;
352 recorder_header.riff_fmt = ID_WAVE;
353 recorder_header.fmt_id = ID_FMT;
354 recorder_header.fmt_sz = 16;
355 recorder_header.audio_format = 1; //FORMAT_PCM;
356 recorder_header.num_channels = 1; //Modem ONLY support mono recording
357 recorder_header.sample_rate = (sample_rate == MBTK_AUDIO_SAMPLE_RATE_8000 ? 8000 : 16000);
358 recorder_header.bits_per_sample = 16; //PCM_SAMPLEBITS_S16_LE;
359 recorder_header.byte_rate = (recorder_header.bits_per_sample / 8) * recorder_header.num_channels * recorder_header.sample_rate;
360 recorder_header.block_align = recorder_header.num_channels * (recorder_header.bits_per_sample / 8);
361 recorder_header.data_id = ID_DATA;
362
363 mbtk_audio_pcm_sample_rate_set(sample_rate);
364
b.liub3b923a2024-06-06 15:15:49 +0800365 wav_recorder_fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
b.liu1c1c7212023-12-22 16:35:27 +0800366 if (wav_recorder_fd < 0) {
367 LOGE("%s: error opening file %s!", __FUNCTION__, path);
368 return -1;
369 }
370
371 //leave enough room for header
372 lseek(wav_recorder_fd, sizeof(struct wav_header), SEEK_SET);
373
374 recorver_data_count = 0;
375
376 return mbtk_audio_pcm_recorder_start(audio_recorder_cb);
377}
378
379int mbtk_audio_wav_recorder_pause()
380{
381 return mbtk_audio_pcm_recorder_pause();
382}
383
384int mbtk_audio_wav_recorder_resume()
385{
386 return mbtk_audio_pcm_recorder_resume();
387}
388
389
390int mbtk_audio_wav_recorder_stop()
391{
392 return mbtk_audio_pcm_recorder_stop();
393}
394
395int mbtk_audio_wav_deinit()
396{
397 if(play_state != AUDIO_PLAY_STATE_STOP) {
398 if(mbtk_audio_wav_play_stop()) {
399 LOGE("mbtk_audio_wav_play_stop() fail.");
400 }
401 }
402
403 if(wav_recorder_fd > 0) {
404 mbtk_audio_wav_recorder_stop();
405 }
406
407 return mbtk_audio_pcm_deinit();
408}
409