123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- /*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-11-24 thread-liu first version
- */
- #include <rtthread.h>
- #include <rtdevice.h>
- #include <dfs_file.h>
- #include <unistd.h>
- #include <stdio.h>
- #include <sys/stat.h>
- #include <sys/statfs.h>
- #if defined(BSP_USING_AUDIO) && defined(BSP_USING_SDMMC)
- #define BUFSZ 1024
- #define SOUND_DEVICE_NAME "sound0"
- static rt_device_t snd_dev;
- struct RIFF_HEADER_DEF
- {
- char riff_id[4]; // 'R','I','F','F'
- uint32_t riff_size;
- char riff_format[4]; // 'W','A','V','E'
- };
- struct WAVE_FORMAT_DEF
- {
- uint16_t FormatTag;
- uint16_t Channels;
- uint32_t SamplesPerSec;
- uint32_t AvgBytesPerSec;
- uint16_t BlockAlign;
- uint16_t BitsPerSample;
- };
- struct FMT_BLOCK_DEF
- {
- char fmt_id[4]; // 'f','m','t',' '
- uint32_t fmt_size;
- struct WAVE_FORMAT_DEF wav_format;
- };
- struct DATA_BLOCK_DEF
- {
- char data_id[4]; // 'R','I','F','F'
- uint32_t data_size;
- };
- struct wav_info
- {
- struct RIFF_HEADER_DEF header;
- struct FMT_BLOCK_DEF fmt_block;
- struct DATA_BLOCK_DEF data_block;
- };
- int wavplay_sample(int argc, char **argv)
- {
- int fd = -1;
- uint8_t *buffer = NULL;
- struct wav_info *info = NULL;
- struct rt_audio_caps caps = {0};
- if (argc != 2)
- {
- rt_kprintf("Usage:\n");
- rt_kprintf("wavplay_sample song.wav\n");
- return 0;
- }
- fd = open(argv[1], O_WRONLY);
- if (fd < 0)
- {
- rt_kprintf("open file failed!\n");
- goto __exit;
- }
- buffer = rt_malloc(BUFSZ);
- if (buffer == RT_NULL)
- goto __exit;
- info = (struct wav_info *) rt_malloc(sizeof * info);
- if (info == RT_NULL)
- goto __exit;
- if (read(fd, &(info->header), sizeof(struct RIFF_HEADER_DEF)) <= 0)
- goto __exit;
- if (read(fd, &(info->fmt_block), sizeof(struct FMT_BLOCK_DEF)) <= 0)
- goto __exit;
- if (read(fd, &(info->data_block), sizeof(struct DATA_BLOCK_DEF)) <= 0)
- goto __exit;
- rt_kprintf("wav information:\n");
- rt_kprintf("samplerate %d\n", info->fmt_block.wav_format.SamplesPerSec);
- rt_kprintf("channel %d\n", info->fmt_block.wav_format.Channels);
- snd_dev = rt_device_find(SOUND_DEVICE_NAME);
- rt_device_open(snd_dev, RT_DEVICE_OFLAG_WRONLY);
- caps.main_type = AUDIO_TYPE_OUTPUT;
- caps.sub_type = AUDIO_DSP_PARAM;
- caps.udata.config.samplerate = info->fmt_block.wav_format.SamplesPerSec;
- caps.udata.config.channels = info->fmt_block.wav_format.Channels;
- caps.udata.config.samplebits = 16;
- rt_device_control(snd_dev, AUDIO_CTL_CONFIGURE, &caps);
- while (1)
- {
- int length;
- length = read(fd, buffer, BUFSZ);
- if (length <= 0)
- break;
- rt_device_write(snd_dev, 0, buffer, length);
- }
- rt_device_close(snd_dev);
- __exit:
- if (fd >= 0)
- close(fd);
- if (buffer)
- rt_free(buffer);
- if (info)
- rt_free(info);
- return 0;
- }
- MSH_CMD_EXPORT(wavplay_sample, play wav file);
- #endif
- #if defined(BSP_USING_AUDIO) && defined(BSP_USING_SDMMC) && defined(BSP_USING_AUDIO_RECORD)
- #define RECORD_TIME_MS 5000
- #define RECORD_SAMPLERATE 16000
- #define RECORD_CHANNEL 2
- #define RECORD_CHUNK_SZ ((RECORD_SAMPLERATE * RECORD_CHANNEL * 2) * 20 / 1000)
- #define MIC_DEVICE_NAME "mic0"
- static rt_device_t mic_dev;
- struct wav_header
- {
- char riff_id[4]; /* "RIFF" */
- int riff_datasize; /* RIFF chunk data size,exclude riff_id[4] and riff_datasize,total - 8 */
- char riff_type[4]; /* "WAVE" */
- char fmt_id[4]; /* "fmt " */
- int fmt_datasize; /* fmt chunk data size,16 for pcm */
- short fmt_compression_code; /* 1 for PCM */
- short fmt_channels; /* 1(mono) or 2(stereo) */
- int fmt_sample_rate; /* samples per second */
- int fmt_avg_bytes_per_sec; /* sample_rate * channels * bit_per_sample / 8 */
- short fmt_block_align; /* number bytes per sample, bit_per_sample * channels / 8 */
- short fmt_bit_per_sample; /* bits of each sample(8,16,32). */
- char data_id[4]; /* "data" */
- int data_datasize; /* data chunk size,pcm_size - 44 */
- };
- static void wavheader_init(struct wav_header *header, int sample_rate, int channels, int datasize)
- {
- memcpy(header->riff_id, "RIFF", 4);
- header->riff_datasize = datasize + 44 - 8;
- memcpy(header->riff_type, "WAVE", 4);
- memcpy(header->fmt_id, "fmt ", 4);
- header->fmt_datasize = 16;
- header->fmt_compression_code = 1;
- header->fmt_channels = channels;
- header->fmt_sample_rate = sample_rate;
- header->fmt_bit_per_sample = 16;
- header->fmt_avg_bytes_per_sec = header->fmt_sample_rate * header->fmt_channels * header->fmt_bit_per_sample / 8;
- header->fmt_block_align = header->fmt_bit_per_sample * header->fmt_channels / 8;
- memcpy(header->data_id, "data", 4);
- header->data_datasize = datasize;
- }
- int wavrecord_sample(int argc, char **argv)
- {
- int fd = -1;
- uint8_t *buffer = NULL;
- struct wav_header header;
- struct rt_audio_caps caps = {0};
- int length, total_length = 0;
- if (argc != 2)
- {
- rt_kprintf("Usage:\n");
- rt_kprintf("wavrecord_sample file.wav\n");
- return -1;
- }
- fd = open(argv[1], O_WRONLY | O_CREAT);
- if (fd < 0)
- {
- rt_kprintf("open file for recording failed!\n");
- return -1;
- }
- write(fd, &header, sizeof(struct wav_header));
- buffer = rt_malloc(RECORD_CHUNK_SZ);
- if (buffer == RT_NULL)
- goto __exit;
- mic_dev = rt_device_find(MIC_DEVICE_NAME);
- if (mic_dev == RT_NULL)
- goto __exit;
- rt_device_open(mic_dev, RT_DEVICE_OFLAG_RDONLY);
- caps.main_type = AUDIO_TYPE_INPUT;
- caps.sub_type = AUDIO_DSP_PARAM;
- caps.udata.config.samplerate = RECORD_SAMPLERATE;
- caps.udata.config.channels = RECORD_CHANNEL;
- caps.udata.config.samplebits = 16;
- rt_device_control(mic_dev, AUDIO_CTL_CONFIGURE, &caps);
- while (1)
- {
- length = rt_device_read(mic_dev, 0, buffer, RECORD_CHUNK_SZ);
- if (length)
- {
- write(fd, buffer, length);
- total_length += length;
- }
- if ((total_length / RECORD_CHUNK_SZ) > (RECORD_TIME_MS / 20))
- break;
- }
- /* write wav file head */
- wavheader_init(&header, RECORD_SAMPLERATE, RECORD_CHANNEL, total_length);
- lseek(fd, 0, SEEK_SET);
- write(fd, &header, sizeof(struct wav_header));
- close(fd);
- /* close audio mic device */
- rt_device_close(mic_dev);
- __exit:
- if (fd >= 0)
- close(fd);
- if (buffer)
- rt_free(buffer);
- return 0;
- }
- MSH_CMD_EXPORT(wavrecord_sample, record voice to a wav file);
- #endif
|