SDL2 PCM音頻播放

SDL2文章列表git

SDL2入門github

SDL2事件處理bash

SDL2紋理渲染函數

原本計劃寫FFmpeg+SDL2視頻播放,可是發現要說的內容有點多,因此仍是先從簡單的音頻數據播放開始,一步一步來。post

打開音頻設備

int SDLCALL SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained);
// desired:指望的參數。
// obtained:實際音頻設備的參數,通常狀況下設置爲NULL便可。
複製代碼

SDL_AudioSpec

//在這個結構體中包含了音頻的各類參數
typedef struct SDL_AudioSpec {
    int freq;                   /**< 音頻採樣率*/
    SDL_AudioFormat format;     /**< 音頻數據格式 */
    Uint8 channels;             /**< 聲道數: 1 單聲道, 2 立體聲 */
    Uint8 silence;              /**< 設置靜音的值*/
    Uint16 samples;             /**< 音頻緩衝區中的採樣個數,要求必須是2的n次*/
    Uint16 padding;             /**< 考慮到兼容性的一個參數*/
    Uint32 size;                /**< 音頻緩衝區的大小,以字節爲單位*/
    SDL_AudioCallback callback; /**< 填充音頻緩衝區的回調函數 */
    void *userdata;             /**< 用戶自定義的數據 */
} SDL_AudioSpec;
複製代碼

SDL_AudioCallback

當音頻設備須要更多數據的時候會調用該回調函數。ui

// userdata:SDL_AudioSpec結構中的用戶自定義數據,通常狀況下能夠不用。
// stream:該指針指向須要填充的音頻緩衝區。
// len:音頻緩衝區的大小(以字節爲單位)。
void (SDLCALL * SDL_AudioCallback) (void *userdata,
                                    Uint8 *stream,
                                    int len);
                                         
複製代碼

播放音頻數據

// 當pause_on設置爲0的時候便可開始播放音頻數據。設置爲1的時候,將會播放靜音的值。
void SDLCALL SDL_PauseAudio(int pause_on) 複製代碼

播放PCM音頻Demo

#include <stdio.h>
#include <tchar.h>
#include <SDL_types.h>
#include "SDL.h"

static Uint8 *audio_chunk;
static Uint32 audio_len;
static Uint8 *audio_pos;
int pcm_buffer_size = 4096;

//回調函數,音頻設備須要更多數據的時候會調用該回調函數
void read_audio_data(void *udata, Uint8 *stream, int len) {
    SDL_memset(stream, 0, len);
    if (audio_len == 0)
        return;
    len = (len > audio_len ? audio_len : len);

    SDL_MixAudio(stream, audio_pos, len, SDL_MIX_MAXVOLUME);
    audio_pos += len;
    audio_len -= len;
}

int WinMain(int argc, char *argv[]) {
    
    if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
        printf("Could not initialize SDL - %s\n", SDL_GetError());
        return -1;
    }
  
    SDL_AudioSpec spec;
    spec.freq = 44100;//根據你錄製的PCM採樣率決定
    spec.format = AUDIO_S16SYS;
    spec.channels = 1; //單聲道
    spec.silence = 0;
    spec.samples = 1024;
    spec.callback = read_audio_data;
    spec.userdata = NULL;

    if (SDL_OpenAudio(&spec, NULL) < 0) {
        printf("can't open audio.\n");
        return -1;
    }

    FILE *fp = fopen("C:\\Users\\lenovo\\Desktop\\1111111.pcm", "rb+");
    if (fp == NULL) {
        printf("cannot open this file\n");
        return -1;
    }
    char *pcm_buffer = (char *) malloc(pcm_buffer_size);

    //播放
    SDL_PauseAudio(0);

    while (1) {
        if (fread(pcm_buffer, 1, pcm_buffer_size, fp) != pcm_buffer_size) { //從文件中讀取數據,剩下的就交給音頻設備去完成了,它播放完一段數據後會執行回調函數,獲取等多的數據
            break;
        }

        audio_chunk = (Uint8 *) pcm_buffer;
        audio_len = pcm_buffer_size; //長度爲讀出數據長度,在read_audio_data中作減法
        audio_pos = audio_chunk;

        while (audio_len > 0) //判斷是否播放完畢
            SDL_Delay(1);
    }
    free(pcm_buffer);
    SDL_Quit();

    return 0;
}
複製代碼

OK!第一步完成,能正常播放出聲音了。this

想要錄製PCM本身試一下?能夠試試用這個Android音視頻(五) OpenSL ES錄製、播放音頻(帶源碼)錄製一段。spa

源碼 GitHub-SimplePlayer指針

相關文章
相關標籤/搜索