Загрузка исходного кода блога : https://download.csdn.net/download/han1202012/89734548
PCM, импульсно-кодовая модуляция, импульсно-кодовая модуляция, использует числа для представления аналоговых сигналов и широко используется при оцифровке звука;
Звук — это тип аналогового сигнала. Звук записывается в данные PCM через микрофон, а затем данные PCM передаются в динамик для воспроизведения звука;
Аудиоданные PCM не сжимаются и представляют собой данные высокой точности без каких-либо потерь звука. После преобразования в формат AAC/MP3 некоторая звуковая информация будет безвозвратно потеряна, например: высокочастотный сигнал/низкочастотный сигнал/информация о маскировании временной области. /частотная область. Информация о маскировании и т. д. удаляются во время сжатия звука;
Параметры данных PCM:
звуковая частотаанализировать : частота звука то есть вокал амплитуда ;
вокаламплитудадействительныйначальствода синус / косинус изгиб,синусизциклчислото естьчастота звука, например : 128 средний центр клавишного фортепиано C примечание Do Частота звуковая частотадля 262 Hz , такжето есть хозяинчастота, вибрирует каждую секунду 262 Второсортный , каждую секунду 262 индивидуальный синус / косинус изгиб цикл , ссылка [Обработка звука] Высота звука и частота сравнительная таблица ( примечаниечастота算法 ) ;
проходить Преобразование Фурье , может быть проанализирован на основе данных аудиообразца звуковая частота , Это есть информация во временной области изменять Информация о частотной области ;
Данные PCM не сжимаются и занимают много места. Одна минута аудиоданных занимает около 11 МБ. При сжатии в формат mp4 или aac их можно сжать до размера менее 1 МБ;
PCM Данные нелегко найти , Эти данные не имеют никакого Заголовок файла Описание информации , Файл из первого индивидуального байта есть 第одининдивидуальныйвыборкаизчислоценитьданные , играть PCM Данные должны быть известны для аудио Частота выборки Количество каналов Количество бит выборки и другие параметры ;
Здесь инструмент командной строки FFmpeg используется для извлечения данных PCM из видео. Следующая команда может извлечь данные PCM из видео в формате mp4;
ffmpeg -i input.mp4 -codec:a pcm_s16le -ar 44100 -ac 2 -f s16le 44100_16bit_2ch.pcm
-i input.mp4
: Укажите входной файл input2.mp4 , -i даиспользуется для Укажите входной файлизпараметр ;-codec:a pcm_s16le
: обозначение Аудиокодек для pcm_s16le , Этот вид PCM Аудио Формат,использовать 16 Маленький порядок байтов s16le , этотиндивидуальныйкодекиспользуется для Воляаудиоданные хранятся в несжатом виде ;-ar 44100
: настраивать Аудио Частота выборкидля 44100 Hz , Частота выборки да Сколько индивидуальных Аудиообразцов собирается в секунду? ;-ac 2
: настраивать Аудио Количество каналовдля 2 , Бинауральный стерео ;-f s16le
: обозначениевыход Форматдля s16le , Это да Аудиоиз оригинал PCM данные Формат ,Чтосередина s16 представлять 16 битовое целое число со знаком, le выполнение с прямым порядком байтов Little Endian ;После получения выходного файла выполните
ffplay -ar 44100 -ac 2 -f s16le 44100_16bit_2ch.pcm
Заказ , Можетигратьначальствоописыватьизвлекатьиз PCM аудиоданные ;
SDL играть PCM Аудио хозяин要分для Следующееиндивидуальныйшаг
инициализация SDL среда , то естьвызов SDL_Init функция ,Эта функция используется для инициализации управления системой SDL., SDL необходимо выполнять перед любой операцией инициализация SDL шаг ;
SDL_Init функцияпрототипследующее, входящий flags Параметры,используемые для установки SDL серединаизгдеиндивидуальный Подсистема, Эта статьяблогсерединана настройки SDL_INIT_AUDIO Аудио подсистема , используется для PCM Аудиоиграть ;
int SDL_Init(Uint32 flags);
специфическийизфункцияпрототипссылка 【FFmpeg】SDL Аудио и видео разработка ① ( SDL рисунок окна | SDL Видео шоуфункция | SDL_Window окно | SDL_Renderer Рендерер | SDL_Texture текстура ) блог Главасередина Содержание главы 1 ;
существовать SDL середина , использовать SDL_AudioSpec Структура Приходитьнастраивать Аудиопараметр , Вид Структура содержит индивидуальные ключевые атрибуты Audioiz. ,Создайтеиндивидуальный SDL_AudioSpec Структура,настраивать Должен Структураизкаждыйиндивидуальныйчленпараметр ;
samples * channels * (SDL_AUDIO_BITSIZE(format) / 8)
;SDL_AudioSpec Структурапрототипследующее :
/*
SDL_AudioSpec Структура Зависит от SDL_OpenAudio() Рассчитано по функции
верно Вмногоканальный Аудио,По умолчанию из SDL голосовой тракткартографированиедля:
2: Передний левый (FL) Передний правый (FR) (стерео)
3: Передний левый (FL) Передний правый (FR) Улучшение низких частот (LFE) (2.1 объемный звук)
4: Передний левый (FL) Передний правый (FR)左назад(BL)右назад(BR)(四голосовой тракт)
5: Передний левый (FL) Передний правый (FR)серединанабор(FC)左назад(BL)右назад(BR)(四голосовой тракт + серединанабор)
6: Передний левый (FL) Передний правый (FR)серединанабор(FC)Улучшение низких частот(LFE)Объемный левый(SL)правильная упаковка(SR)(5.1 объемный звук - Последние два индивидуальных также "Мандада" остались позади BL сразу назад BR)
7: Передний левый (FL) Передний правый (FR)серединанабор(FC)Улучшение низких частот(LFE)назаднаборсерединанабор(BC)Объемный левый(SL)правильная упаковка(SR)(6.1 объемный звук)
8: Передний левый (FL) Передний правый (FR)серединанабор(FC)Улучшение низких частот(LFE)左назад(BL)右назад(BR)Объемный левый(SL)правильная упаковка(SR)(7.1 объемный звук)
*/
typedef struct SDL_AudioSpec {
int freq; // выборкачастота(Sample Rate)
SDL_AudioFormat format; // аудиоданные Формат
Uint8 channels; // Количество каналов(1 = мононуклеоз, 2 = стерео, etc.)
Uint8 silence; // значение отключения звука(Каждыйиндивидуальныйобразецизнемойбайтценить)
Uint16 samples; // Аудиобуферсерединаизобразецчисло
Uint16 padding; // Необходимо указать значение заполнения, чтобы гарантировать, что размер структуры для является четным (используется для некоторых платформ из выравнивания)
Uint32 size; // Аудио буфер из общего количества байт (= samples * channels * (SDL_AUDIO_BITSIZE(format) / 8))
void *userdata; // Пользовательский указатель данных (может Зависит от Разработано Зависит отиспользовать)
Uint8 *buffer; // Фактические аудиоданныеиз указатель
unsigned int length; // Длина аудиобуфера (в байтах для одного Кусочка) (существовать) SDL 2.0.9 середина Устарело,предположениеиспользовать size поле)
} SDL_AudioSpec;
SDL_AudioSpec Структуранастраивать示例 :
#include <SDL2/SDL.h>
int main() {
SDL_AudioSpec spec;
// настраиватьвыборка Частота 44100 Hz
spec.freq = 44100;
// настраивать Аудио Форматдля 16-bit знакцелое число, порядок системных байтов
spec.format = AUDIO_S16SYS;
// настраиватьдлястерео(2 индивидуальныйголосовой тракт)
spec.channels = 2;
// настраиватьзначение отключения звукадля 0 (для 16-bit знакцелое число,в целомиспользовать 0)
spec.silence = 0;
// настраивать Каждыйиндивидуальныйбуферизобразецчислодля 1024
spec.samples = 1024;
// Вычислить общее количество байт в аудиобуфере из
spec.size = spec.samples * spec.channels * (SDL_AUDIO_BITSIZE(spec.format) / 8);
// Набор указателей данных пользователя для NULL (без настройки)
spec.userdata = NULL;
// Выделить буфер аудио (требуется выделение памяти вручную)
spec.buffer = (Uint8 *)SDL_malloc(spec.size);
// Убедитесь, что выделение памяти прошло успешно
if (spec.buffer == NULL) {
SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "Failed to allocate audio buffer");
return -1;
}
// создание буфера для отключения звука (опционально)
SDL_memset(spec.buffer, spec.silence, spec.size);
// ... использовать spec Сделать аудиоиграть или захватить ...
// выделить из буфера
SDL_free(spec.buffer);
return 0;
}
SDL_OpenAudio функция используется для настраивать Аудиопараметр и Откройте аудиоустройство , для последующей подготовки к аудиоиграм ;
SDL_OpenAudio функцияпрототипследующее :
int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained);
SDL_AudioSpec *desired
параметр : настройки ожиданий пользователей из конфигурации Audio ;SDL_AudioSpec *obtained
параметр : Фактический параметр аудиооборудования ,существовать Эта статьяблогсерединавременныйнастраиватьдля NULL ;SDL_AudioCallback да SDL ( Simple DirectMedia Layer ) Библиотекасерединаиз PCM Аудиоиграть Тип обратного вызова ,когда SDL игратьнадкогдавперед Аудиобуферсерединаизданныеназад, Автоматически перезвонит функции , для Аудио оборудование обеспечивает последующее сопровождение Аудиоигратьданные , Основная роль функцииследующее :
почти все PCM Аудиоиграть необходимо для предоставления индивидуальной функции обратного звонка , OpenSL / AAudio Существует также индивидуальная функция, похожая на функцию обратного вызова. ;
SDL_AudioCallback функцияпрототип :
/**
* Когда аудиооборудование вам нужно больше данных, волявызов эту функцию.
*
* \param userdata 保存существовать SDL_AudioSpec Структура серединаиз конкретного параметра приложения
* \param stream Каудиодированный буфер из указателя
* \param len Длина буфера (в байтах)
*
* Как только функция обратного вызова возвращается, буфер Воля больше не действителен.
* стерео Аудиообразец с LRLRLR из Последовательное хранение.
*
* Если вы предпочитаете нравиться, вы можете отказаться от использования функции обратного вызова и использовать вместо нее SDL_QueueAudio()。
* Толькоиспользовать NULL Просто перезвоните и откройте свое аудиоустройство.
*/
typedef void (SDLCALL * SDL_AudioCallback) (void *userdata, Uint8 * stream,
int len);
void *userdata
параметр : Относится к указателю определяемых пользователем данных. , существовать в середине функции Этот указатель можно использовать Доступ для хранения дополнительной информации ;Uint8 * stream
параметр : Каудиодированный буфер из указателя ,Воляаудиоданные写入этотиндивидуальныйбуфер,Сразу Можетодеяло Аудиооборудованиеиграть ;int len
параметр : Длина буфера в байтах , использовать Необходимо убедиться, что длина изданных записей в буфер К не превышает это индивидуальное значение. ;существовать Этот примерсередина , осуществленный SDL_AudioCallback перезвонитьфункция следующее :
// один кадр PCM данныеиметь 1024 индивидуальныйвыборкаточка
// Каждыйиндивидуальныйвыборка Да 2 ряд стерео ( о канале ) , Каждыйиндивидуальныйрядизвыборка Да 16 Кусочек (bit) такжето есть 2 байт (Byte)
// Каждый Второсортныйчитать 2 рамка PCM данные
// 1024 ( выборкачисло ) * 2 ( Количество каналов ) * 2 ( 2 байт / 16 Кусочек ) * 2 ( рамкачислодля 2 рамка )
#define PCM_BUFFER_SIZE (1024 * 2 * 2 * 2)
// АудиоPCMданные указатель кэша
static Uint8 *s_audio_buf = NULL;
// когдавпередчитатьиз Кусочекнабор
static Uint8 *s_audio_pos = NULL;
// Настройка конца кеша Кусочек
static Uint8 *s_audio_end = NULL;
// Функция обратного вызова аудиоустройства
void fill_audio_pcm(void *udata, Uint8 *stream, int len)
{
SDL_memset(stream, 0, len); // Воля Инициализация буфера потоковой передачи для 0
if(s_audio_pos >= s_audio_end) // нравитьсяфруктыданныеужечитатьнад毕 {
return; // покидатьперезвонитьфункция }
// Когда данных достаточно, прочитайте длину по умолчанию. Если данных недостаточно, остается только чтение.
int remain_buffer_len = s_audio_end - s_audio_pos;
len = (len < remain_buffer_len) ? len : remain_buffer_len;
// Воляданные копии приезжатьстримы отрегулировать громкость
SDL_MixAudio(stream, s_audio_pos, len, SDL_MIX_MAXVOLUME/8);
printf("len = %d\n", len); // Длина предварительно считанных данных при выводе
s_audio_pos += len; // Переместите указатель кэша на следующий индивидуальный Кусочек
}
вызов SDL_PauseAudio функция Может восстанавливаться / пауза игратьаудиоданные ;
SDL_PauseAudio функцияпрототипследующее :
void SDL_PauseAudio(int pause_on);
int pause_on
параметр даодининдивидуальныйцелое числоценить , Определяет состояние аудиооборудования ;
Некоторые примеры кода:
#include <SDL2/SDL.h>
int main() {
// инициализация SDL
if (SDL_Init(SDL_INIT_AUDIO) < 0) {
// Обработка ошибок
return -1;
}
// Откройте аудиоустройство、настраивать Аудиоперезвонитьждать(немного)
// начать воспроизводить аудио
SDL_PauseAudio(0); // передача 0 выражатьвосстанавливаться Аудиоиграть
// существоватьподходящийкогдаизкогдапауза Аудио
SDL_PauseAudio(1); // передача 1 выражатьпауза Аудиоиграть
// Завершить аудиоиграть, очистить ресурсы ожидания (опущено)
// убирать SDL
SDL_Quit();
return 0;
}
играть После окончания вызов SDL_CloseAudio функция , Выключите аудиоустройство , выпускать PCM Подайте заявку на системные ресурсы, когда играете ;
SDL_CloseAudio функцияпрототипследующее, Долженфункцияиспользуется для Выключите аудиоустройство ;
void SDL_CloseAudio(void);
Некоторые примеры кода:
#include <SDL/SDL.h>
int main() {
// инициализация SDL
if (SDL_Init(SDL_INIT_AUDIO) < 0) {
// Обработка ошибок
return -1;
}
// настраивать Аудиопараметри Откройте аудиоустройство(немного)
// Выключите аудиоустройство
SDL_CloseAudio();
// убирать SDL
SDL_Quit();
return 0;
}
Пример кода:
#include <SDL2/SDL.h>
#include <stdio.h>
// Аудиоперезвонитьфункция
void audio_callback(void *userdata, Uint8 *stream, int len) {
// этот里заполнить аудиоданныеприезжать stream середина
// len данужно заполнитьизбайтчисло
SDL_memset(stream, 0, len); // Просто Воля буфер приглушен
}
int main(int argc, char *argv[]) {
// инициализация SDL Аудио подсистема
if (SDL_Init(SDL_INIT_AUDIO) < 0) {
printf("SDL Не могущийинициализация! SDL_Error: %s\n", SDL_GetError());
return -1;
}
// Настройка параметров аудиооборудования
SDL_AudioSpec desired;
desired.freq = 44100; // выборкачастота 44.1kHz
desired.format = SDL_AUDIO_S16SYS; // Аудио Формат:16 Короткая последовательность системных байтов
desired.channels = 2; // стерео
desired.samples = 4096; // Каждый Второсортныйперезвонитьизобразецчисло
desired.callback = audio_callback; // Аудиоперезвонитьфункция
desired.userdata = NULL; // Данные пользователя (здесь не использовать)
SDL_AudioSpec obtained;
// Откройте аудиоустройство
if (SDL_OpenAudio(&desired, &obtained) < 0) {
printf("Не могущий Откройте аудиоустройство! SDL_Error: %s\n", SDL_GetError());
SDL_Quit();
return -1;
}
// существоватьэтот里,Вы можетеначать воспроизводить аудио Понятно
// Например,ты Можетвызов SDL_PauseAudio(0) Давайте начнем
// начать воспроизводить аудио
SDL_PauseAudio(0);
// ПРИМЕЧАНИЕ. Чтобы действительно применить середину, вам нужен цикл или какой-то способ сохранить функцию обратного вызова вызова.
// Здесь мы лишь показываем примеры и упрощаем код.
// когдатынад成Аудиоигратьназад,Помнить Выключите аудиоустройство
SDL_CloseAudio();
SDL_Quit();
return 0;
}
// Импортные стандарты IO Библиотека
#include <stdio.h>
// импортировать SDL Заголовочный файл библиотеки
#include <SDL.h>
// один кадр PCM данныеиметь 1024 индивидуальныйвыборкаточка
// Каждыйиндивидуальныйвыборка Да 2 ряд стерео ( о канале ) , Каждыйиндивидуальныйрядизвыборка Да 16 Кусочек (bit) такжето есть 2 байт (Byte)
// Каждый Второсортныйчитать 2 рамка PCM данные
// 1024 ( выборкачисло ) * 2 ( Количество каналов ) * 2 ( 2 байт / 16 Кусочек ) * 2 ( рамкачислодля 2 рамка )
// Каждый Второсортныйот местный PCM данныедокументсерединачитать 1024 * 2 * 2 * 2 байтиз Аудио данные
#define PCM_BUFFER_SIZE (1024 * 2 * 2 * 2)
// Аудио PCM указатель кэша данных , Этот указатель ссылается на кучу памяти Киз, содержащую полную информацию. PCM документданные
static Uint8 *s_audio_buf = NULL;
// когдавпередчитатьиз Кусочекнабор , К используется при начале игры s_audio_buf Указатель указывает на первый адрес Кданныеиз.
static Uint8 *s_audio_pos = NULL;
// Настройка конца кеша Кусочек , Обратитесь к s_audio_buf 指针Обратитесь кданныеиз хвостовой адрес , Предотвратить выход данных за пределы границ неизвестная ошибка
static Uint8 *s_audio_end = NULL;
// Функция обратного вызова аудиоустройства
void fill_audio_pcm(void *udata, Uint8 *stream, int len)
{
// Очистить буфер ,Воля流буферинициализациядля 0, Данные о предотвращении помех
SDL_memset(stream, 0, len);
// Убедитесь, что при чтении не происходит выхода за пределы , читатьприезжать Что它未知данные if(s_audio_pos >= s_audio_end) // нравитьсяфруктыданныеужечитатьнад毕 {
return; // покидатьперезвонитьфункция }
// Рассчитать оставшиеся данные : данных достаточно, чтобы прочитать длину по умолчанию , Когда данных недостаточно, остается только чтение.
// 之впередчитатьизданные Да len байт
// последней части недостаточно len время байта , читать remain_buffer_len байтданные
int remain_buffer_len = s_audio_end - s_audio_pos;
len = (len < remain_buffer_len) ? len : remain_buffer_len;
// Воляданные копии приезжатьстримы отрегулировать громкость
SDL_MixAudio(stream, s_audio_pos, len, SDL_MIX_MAXVOLUME/8);
printf("len = %d\n", len); // Длина предварительно считанных данных при выводе
s_audio_pos += len; // Переместите указатель кэша на следующий индивидуальный Кусочек
}
// использовать ffmpeg Заказ извлекать PCM данные :
// ffmpeg -i input.mp4 -codec:a pcm_s16le -ar 44100 -ac 2 -f s16le 44100_16bit_2ch.pcm
// использовать ffplay Заказ играть PCM данные ,играть PCM данныедолженобозначение Частота выборки / Количество каналов / Количество бит выборки
// ffplay -ar 44100 -ac 2 -f s16le 44100_16bit_2ch.pcm
#undef main
int main(int argc, char *argv[])
{
int ret = -1; // Возвращаемое значение инициализациядля-1
FILE *audio_fd = NULL; // Указатель файла: организациядля пустого
SDL_AudioSpec spec; // SDLАудио Технические характеристики
const char *path = "44100_16bit_2ch.pcm"; // Путь к файлу PCM
// Длина кэша на Второсортный
size_t read_buffer_len = 0;
// инициализацияSDLАудио
if(SDL_Init(SDL_INIT_AUDIO)) // инициализацияSDLАудиоподдерживать {
fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError()); // Выходное сообщение об ошибке
return ret; // Возврат кода ошибки
}
// Открыть файл ПКМ
audio_fd = fopen(path, "rb"); // Открыть в режиме только для чтения файл ПКМ
if(!audio_fd)
{
fprintf(stderr, "Failed to open pcm file!\n"); // Не удалось открыть файл
goto _FAIL; // Перейти внесены измененияпризаезезз обработка сбоев
}
s_audio_buf = (uint8_t *)malloc(PCM_BUFFER_SIZE); // для Аудио буфер выделяет память
// настраивать АудиопараметрSDL_AudioSpec
spec.freq = 44100; // выборка Частота44100Hz
spec.format = AUDIO_S16SYS; // выборкаточка Форматдля16Кусочексистема Формат spec.channels = 2; // 2ряд
spec.silence = 0; // значение отключения звукадля0
spec.samples = 1024; // Каждый Второсортныйчитать1024индивидуальныйвыборкаточка spec.callback = fill_audio_pcm; // настраивать Аудиоперезвонитьфункция
spec.userdata = NULL; // пользовательданныедлянулевой // Откройте аудиоустройство
if(SDL_OpenAudio(&spec, NULL))
{
fprintf(stderr, "Failed to open audio device, %s\n", SDL_GetError()); // Откройте аудиоустройство не удалось
goto _FAIL; // Перейти внесены измененияпризаезезз обработка сбоев
}
// начать воспроизводить аудио
SDL_PauseAudio(0); // Отменить статус Аудиопаузы
int data_count = 0; // данные计число器инициализациядля0 while(1)
{
// Из файлачитатьPCMданные
read_buffer_len = fread(s_audio_buf, 1, PCM_BUFFER_SIZE, audio_fd); // читатьPCMданныеприезжать缓存 if(read_buffer_len == 0)
{
break; // нравиться Если данных больше нет, то выйти из цикла
}
data_count += read_buffer_len; // 累加читатьизданныеобщийбайтчисло
printf("now playing %10d bytes data.\n",data_count); // выходкогдавпередигратьизданныебайтчисло
s_audio_end = s_audio_buf + read_buffer_len; // Обновить кеш из настроек Конец Кусочек
s_audio_pos = s_audio_buf; // Обновить кэш из настройки Кусочек
// Главный поток ожидания ожидает использования данных PCM.
while(s_audio_pos < s_audio_end)
{
SDL_Delay(10); // подожди подожди 10 миллисекунд
}
}
printf("play PCM finish\n"); // играть Полные советы
// Выключите аудиоустройство
SDL_CloseAudio(); // Выключите аудиоустройство
_FAIL:
// выпускатьресурс if(s_audio_buf)
free(s_audio_buf); // выпускать аудиокэш-память
if(audio_fd)
fclose(audio_fd); // закрыть файл
// покидатьSDL
SDL_Quit(); // покидатьSDLБиблиотека
return 0; // Возврат кода успеха
}
Зависит от Вигратьизда Аудио , При использовании игры нет оконного интерфейса. ;
от视频серединаизвлекатьиз из PCM аудиоданные, Копия прибыла Скомпилируйте вывод из файла, находящегося в корневом каталоге середина. ;