Аудио функции включают в себяАудиовход, аудиовыход, эхоподавление, кодирование звука и декодирование звука 5 модуль.
Существуют понятия устройств и каналов аудиовхода и аудиовыхода. Один микрофон считается устройством, и микрофон может иметь несколько входов каналов. Один и тот же SPK считается устройством воспроизведения, и SPK также может иметь несколько выходов каналов. Текущая версия аудио API поддерживает только один канал для каждого устройства. (T31 имеет только один вход и один выход)
Эхоподавление находится в интерфейсе аудиовхода, а конкретные инструкции отражены в описании функции.
PCM:Необработанный поток аудиоданных, исходящий из большинства чипов。
G711A&G711U:
G711 — это набор стандартов сжатия голоса, разработанный Международным союзом электросвязи ITU-T. Он представляет собой стандарт логарифмической выборки PCM (логарифмическая импульсно-кодовая модуляция) и в основном используется для телефонов. В основном он использует импульсно-кодовую модуляцию для выборки звука с частотой дискретизации 8k в секунду. Для передачи голосовых сигналов он использует несжатый канал со скоростью 64 Кбит/с. Начальная степень сжатия составляет 1:2, то есть 16-битные данные сжимаются в 8 бит. G.711 — это основной кодек звукового сигнала.
В стандарте G.711 существует два основных алгоритма сжатия. Один из них — алгоритм u-law (также известный как u-law, ulaw, mu-law), который в основном используется в Северной Америке и Японии, другой — алгоритм A-law, который в основном используется в Европе и других частях страны; мир. Среди них последний специально разработан для облегчения компьютерной обработки.
Содержимое G711 предназначено для кодирования 14-битных (uLaw) или 13-битных (aLaw) дискретизированных данных PCM в 8-битный поток данных. Во время воспроизведения 8-битные данные восстанавливаются до 14-битных или 13-битных данных для воспроизведения. В отличие от MPEG, который не обрабатывает общий или 13-битный формат. Фрагмент данных рассматривается перед кодированием и декодированием G711 — это алгоритм кодирования и декодирования формы сигнала, то есть одна выборка соответствует одному кодированию, поэтому степень сжатия фиксируется как:
8/14 = 57% (uLaw)
8/13 = 62% (aLaw) Просто поймите, G.711 - это нелинейное квантование голосовых аналоговых сигналов, битрейт 64кбит/с.
AAC:
AAC, полное название Advanced Audio Coding, китайское название: Advanced Audio Coding, представляет собой формат сжатия файлов, специально разработанный для звуковых данных. В отличие от MP3, он использует новый алгоритм кодирования, который более эффективен и имеет более высокую «экономичность». Использование формата AAC может заставить людей почувствовать, что качество звука существенно не снижается и он становится более компактным. Мобильные телефоны Apple iPod и Nokia поддерживают аудиофайлы в формате AAC.
Кодирование звука. Текущий API аудио поддерживает кодирование звука в форматах PT_G711A, PT_G711U и PT_G726.
Если вам нужно добавить новый метод кодирования, вам необходимо зарегистрировать кодировщик.
Декодирование звука. Текущий API-интерфейс аудио поддерживает декодирование звука в форматах PT_G711A, PT_G711U и PT_G726.
Если вам нужно добавить новый метод декодирования, вам необходимо зарегистрировать декодер.
Ниже мы рисуем блок-схему работы системы: Схема процесса сбора аудио.
Под MIC подразумевается микрофон, который используется для сбора внешних звуков, сбора аналоговых сигналов, преобразования их в цифровые сигналы через чип T31 и последующего сохранения их в файлы определенного формата.
Ingenic T31SDK предоставляет пример кода о том, как получить необработанные аудиоданные из чипа T31 и сохранить их во флэш-памяти.
В нем есть несколько функций, которые необходимо объяснить:
_ai_basic_record_test_thread:Все наши операции выполняются в этом потоке,Вы можете понимать это как задачу.
IMP_AI_SetPubAttr:
int devID = 1; //devID:0: цифровой микрофон, 1: представляет аналоговый микрофон
IMPAudioIOAttr attr;
attr.samplerate = AUDIO_SAMPLE_RATE_16000; //Частота дискретизации звука 16000
attr.bitwidth = AUDIO_BIT_WIDTH_16; //Точность дискретизации звука 16 бит
attr.soundmode = AUDIO_SOUND_MODE_MONO; //Применить монорежим
attr.frmNum = 40; //Количество буферизованных кадров
attr.numPerFrm = 640; //Количество точек выборки на кадр
attr.chnCnt = 1; //Количество поддерживаемых каналов
ret = IMP_AI_SetPubAttr(devID, &attr);
/* Step 6: get audio record frame. */
/*Используйте этот интерфейс перед использованием IMP_AI_GetFrame. При успешном вызове интерфейса отображается аудио.
Данные подготовлены, и вы можете использовать IMP_AI_GetFrame для получения аудиоданных*/
ret = IMP_AI_PollingFrame(devID, chnID, 1000);
if (ret != 0 ) {
IMP_LOG_ERR(TAG, "Audio Polling Frame Data error\n");
}
/*
* @param[in] audioDevId Номер аудиоустройства.
* @param[in] aiChn Номер входного аудиоканала.
* @param[out] frm Указатель структуры аудиокадра.
* @param[in] block Флаг блокировки/неблокировки.
*/
IMPAudioFrame frm;
ret = IMP_AI_GetFrame(devID, chnID, &frm, BLOCK);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio Get Frame Data error\n");
return NULL;
}
/* Step 8: release the audio record frame. */
ret = IMP_AI_ReleaseFrame(devID, chnID, &frm);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio release frame data error\n");
return NULL;
}
/*
* Ingenic IMP AI implement.
*
* Copyright (C) 2017 Ingenic Semiconductor Co.,Ltd
*
*/
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/prctl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdint.h>
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include <fcntl.h>
#include <sys/time.h>
#include <imp/imp_audio.h>
#include <imp/imp_log.h>
#define TAG "Sample-AI"
#define AI_BASIC_TEST_RECORD_FILE "ai_lbb.pcm"
#define AI_BASIC_TEST_RECORD_NUM 600
static void *_ai_basic_record_test_thread(void *argv)
{
int ret = -1;
int record_num = 0;
FILE *record_file = fopen(AI_BASIC_TEST_RECORD_FILE, "wb");
if(record_file == NULL) {
IMP_LOG_ERR(TAG, "fopen %s failed\n", AI_BASIC_TEST_RECORD_FILE);
return NULL;
}
/* Step 1: set public attribute of AI device. */
int devID = 1;
IMPAudioIOAttr attr;
attr.samplerate = AUDIO_SAMPLE_RATE_16000;
attr.bitwidth = AUDIO_BIT_WIDTH_16;
attr.soundmode = AUDIO_SOUND_MODE_MONO;
attr.frmNum = 40;
attr.numPerFrm = 640;
attr.chnCnt = 1;
ret = IMP_AI_SetPubAttr(devID, &attr);
if(ret != 0) {
IMP_LOG_ERR(TAG, "set ai %d attr err: %d\n", devID, ret);
return NULL;
}
memset(&attr, 0x0, sizeof(attr));
ret = IMP_AI_GetPubAttr(devID, &attr);
if(ret != 0) {
IMP_LOG_ERR(TAG, "get ai %d attr err: %d\n", devID, ret);
return NULL;
}
IMP_LOG_INFO(TAG, "Audio In GetPubAttr samplerate : %d\n", attr.samplerate);
IMP_LOG_INFO(TAG, "Audio In GetPubAttr bitwidth : %d\n", attr.bitwidth);
IMP_LOG_INFO(TAG, "Audio In GetPubAttr soundmode : %d\n", attr.soundmode);
IMP_LOG_INFO(TAG, "Audio In GetPubAttr frmNum : %d\n", attr.frmNum);
IMP_LOG_INFO(TAG, "Audio In GetPubAttr numPerFrm : %d\n", attr.numPerFrm);
IMP_LOG_INFO(TAG, "Audio In GetPubAttr chnCnt : %d\n", attr.chnCnt);
/* Step 2: enable AI device. */
ret = IMP_AI_Enable(devID);
if(ret != 0) {
IMP_LOG_ERR(TAG, "enable ai %d err\n", devID);
return NULL;
}
/* Step 3: set audio channel attribute of AI device. */
int chnID = 0;
IMPAudioIChnParam chnParam;
chnParam.usrFrmDepth = 40;
ret = IMP_AI_SetChnParam(devID, chnID, &chnParam);
if(ret != 0) {
IMP_LOG_ERR(TAG, "set ai %d channel %d attr err: %d\n", devID, chnID, ret);
return NULL;
}
memset(&chnParam, 0x0, sizeof(chnParam));
ret = IMP_AI_GetChnParam(devID, chnID, &chnParam);
if(ret != 0) {
IMP_LOG_ERR(TAG, "get ai %d channel %d attr err: %d\n", devID, chnID, ret);
return NULL;
}
IMP_LOG_INFO(TAG, "Audio In GetChnParam usrFrmDepth : %d\n", chnParam.usrFrmDepth);
/* Step 4: enable AI channel. */
ret = IMP_AI_EnableChn(devID, chnID);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio Record enable channel failed\n");
return NULL;
}
/* Step 5: Set audio channel volume. */
int chnVol = 60;
ret = IMP_AI_SetVol(devID, chnID, chnVol);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio Record set volume failed\n");
return NULL;
}
ret = IMP_AI_GetVol(devID, chnID, &chnVol);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio Record get volume failed\n");
return NULL;
}
IMP_LOG_INFO(TAG, "Audio In GetVol vol : %d\n", chnVol);
int aigain = 28;
ret = IMP_AI_SetGain(devID, chnID, aigain);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio Record Set Gain failed\n");
return NULL;
}
ret = IMP_AI_GetGain(devID, chnID, &aigain);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio Record Get Gain failed\n");
return NULL;
}
IMP_LOG_INFO(TAG, "Audio In GetGain gain : %d\n", aigain);
while(1) {
/* Step 6: get audio record frame. */
ret = IMP_AI_PollingFrame(devID, chnID, 1000);
if (ret != 0 ) {
IMP_LOG_ERR(TAG, "Audio Polling Frame Data error\n");
}
IMPAudioFrame frm;
ret = IMP_AI_GetFrame(devID, chnID, &frm, BLOCK);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio Get Frame Data error\n");
return NULL;
}
printf("seq = %d,timeStamp = %lld\n",frm.seq,frm.timeStamp);
/* Step 7: Save the recording data to a file. */
fwrite(frm.virAddr, 1, frm.len, record_file);
/* Step 8: release the audio record frame. */
ret = IMP_AI_ReleaseFrame(devID, chnID, &frm);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio release frame data error\n");
return NULL;
}
if(++record_num >= AI_BASIC_TEST_RECORD_NUM)
break;
}
sleep(3);
/* Step 9: disable the audio channel. */
ret = IMP_AI_DisableChn(devID, chnID);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio channel disable error\n");
return NULL;
}
/* Step 10: disable the audio devices. */
ret = IMP_AI_Disable(devID);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio device disable error\n");
return NULL;
}
fclose(record_file);
pthread_exit(0);
}
int main(void)
{
int ret = -1;
pthread_t record_thread_id;
printf("[INFO] Test 1: Start audio record test.\n");
printf("[INFO] : Can create the %s file.\n", AI_BASIC_TEST_RECORD_FILE);
printf("[INFO] : Please input any key to continue.\n");
getchar();
/* Step 1: Start audio recording thread. */
ret = pthread_create(&record_thread_id, NULL, _ai_basic_record_test_thread, NULL);
if(ret != 0) {
IMP_LOG_ERR(TAG, "[ERROR] %s: pthread_create Audio Record failed\n", __func__);
return -1;
}
pthread_join(record_thread_id, NULL);
return 0;
}