SDL Audio 相关API

Audio相关的API很少,按几个功能分别列一下,下文中的图是用visio画的,其中颜色表示看下图的标识


1.音频子系统操作 API

SDL_Init(SDL_INIT_AUDIO)
SDL_Quit(void)
SDL_AudioInit(const char* driver_name)
SDL_AudioQuit


其中的SDL_AudioInit、SDL_AudioQuit一般在内部使用,除非特别要指定使用的音频驱动程序,否则通常用SDL_Init()、SDL_InitSubSyste()、SDL_Quit() 、 SDL_QuitSubSystem()


2.操作音频设备 API

SDL_OpenAudio(SDL_AudioSpec* desired,SDL_AudioSpec* obtained)
SDL_OpenAudioDevice(const char* device, int iscapture,
const SDL_AudioSpec* desired,SDL_AudioSpec* obtained, int allowed_changes)
SDL_CloseAudio(void)
SDL_CloseAudioDevice
SDL_PauseAudio(int pause_on)
SDL_PauseAudioDevice(SDL_AudioDeviceID dev,int pause_on)
SDL_LockAudio(void)
SDL_LockAudioDevice(SDL_AudioDeviceID dev)
SDL_UnlockAudio(void)
SDL_UnlockAudioDevice(SDL_AudioDeviceID dev)



3.将音频转换为需要的格式 API

SDL_BuildAudioCVT(SDL_AudioCVT* cvt,SDL_AudioFormat src_format,Uint8 src_channels,
                      int src_rate,SDL_AudioFormat dst_format,Uint8 dst_channels,int dst_rate)
SDL_ConvertAudio(SDL_AudioCVT* cvt)



4.按指定的格式混合音频数据,用来回调

SDL_MixAudio(Uint8* dst,const Uint8* src,Uint32 len, int volume)
SDL_MixAudioFormat(Uint8* dst,const Uint8* src,SDL_AudioFormat format,Uint32 len, int volume)



5.获取音频设备相关信息API

SDL_GetNumAudioDevices(int iscapture)
SDL_GetNumAudioDrivers(void)
SDL_GetAudioDeviceName(int index, int iscapture)
SDL_GetAudioDeviceStatus(SDL_AudioDeviceID dev)
SDL_GetCurrentAudioDriver(void)
SDL_GetAudioStatus(void)
SDL_GetAudioDriver(int index)


6.音频队列处理

SDL_QueueAudio(SDL_AudioDeviceID dev,const void* data,Uint32 len)
SDL_DequeueAudio
SDL_GetQueuedAudioSize
SDL_ClearQueuedAudio(SDL_AudioDeviceID dev)

这系列的函数在2.0.4上开始支持,在非回调设备上使用。
在创建队列之前之前,不应该在设备上调用SDL_LockAudio(); SDL在内部处理这个功能的锁定。


音频播放过程

1.初始化音频子系统(SDL_Init(SDL_INIT_AUDIO))

2.打开音频设备(SDL_OpenAudio(SDL_AudioSpec* desired,SDL_AudioSpec* obtained)),需要填充SDL_AudioSpec结构体

3.播放音频(SDL_PauseAudio(int pause_on)),//参数pause_on:非零暂停,零则播放,播放过程中需要一个回调函数去获取音频数据


以下示例程序来自github和官网,可用来增加对API的了解,全部程序在VS2013上测试运行没问题

获取音频设备的相关信息:

项目下载地址:http://download.csdn.NET/detail/kiazhu/9745344


  1. // testSDL_AudioSample.cpp : 定义控制台应用程序的入口点。  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5.   
  6. #include "include\SDL.h"  
  7. #include "include\SDL_audio.h"  
  8.   
  9.   
  10. void print_devices(int iscapture)  
  11. {  
  12.     const charchar *typestr = ((iscapture) ? "capture" : "output");  
  13.     int n = SDL_GetNumAudioDevices(iscapture);  
  14.   
  15.     printf("Found %d %s device%s:\n", n, typestr, n != 1 ? "s" : "");  
  16.   
  17.     if (n == -1)  
  18.         printf("  Driver can't detect specific %s devices.\n\n", typestr);  
  19.     else if (n == 0)  
  20.         printf("  No %s devices found.\n\n", typestr);  
  21.     else {  
  22.         int i;  
  23.         for (i = 0; i < n; i++) {  
  24.             const charchar *name = SDL_GetAudioDeviceName(i, iscapture);  
  25.             if (name != NULL)  
  26.                 printf("  %d: %s\n", i, name);  
  27.             else  
  28.                 printf("  %d Error: %s\n", i, SDL_GetError());  
  29.         }  
  30.         printf("\n");  
  31.     }  
  32. }  
  33.   
  34. int _tmain(int argc, _TCHAR* argv[])  
  35. {  
  36.     int n;  
  37.   
  38.     /* Load the SDL library */  
  39.     if (SDL_Init(SDL_INIT_AUDIO) < 0) {  
  40.         printf("Couldn't initialize SDL: %s\n", SDL_GetError());  
  41.         return (1);  
  42.     }  
  43.     else{  
  44.         printf("init SDL success.\n");  
  45.     }  
  46.   
  47.     /* Print available audio drivers */  
  48.     n = SDL_GetNumAudioDrivers();  
  49.     if (n == 0) {  
  50.         printf("No built-in audio drivers\n\n");  
  51.     }  
  52.     else {  
  53.         int i;  
  54.         printf("Built-in audio drivers:\n");  
  55.         for (i = 0; i < n; ++i) {  
  56.             printf("  %d: %s\n", i, SDL_GetAudioDriver(i));  
  57.         }  
  58.         printf("Select a driver with the SDL_AUDIODRIVER environment variable.\n");  
  59.     }  
  60.   
  61.     printf("Using audio driver: %s\n\n", SDL_GetCurrentAudioDriver());  
  62.   
  63.     //参数:0表示回放设备,1表示录制设备  
  64.     print_devices(0);  
  65.     print_devices(1);  
  66.   
  67.     switch (SDL_GetAudioStatus())  
  68.     {  
  69.     case SDL_AUDIO_STOPPED: printf("Current Audio Status:stopped\n"); break;  
  70.     case SDL_AUDIO_PLAYING: printf("Current Audio Status:playing\n"); break;  
  71.     case SDL_AUDIO_PAUSED: printf("Current Audio Status:paused\n"); break;  
  72.     default: printf("Current Audio Status:???"); break;  
  73.     }  
  74.   
  75.     SDL_Quit();  
  76.       
  77.     return 0;  
  78. }  

运行结果:

插入耳机前:


插入耳机后:




录音并回放:

  1. // testSDL_AudioCapture.cpp : 定义控制台应用程序的入口点。  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5.   
  6. extern "C"  
  7. {  
  8. #include "include\SDL.h"  
  9. #include "include\SDL_audio.h"  
  10. }  
  11.   
  12. static SDL_Window *window = NULL;  
  13. static SDL_Renderer *renderer = NULL;  
  14. static SDL_AudioSpec spec;  
  15. static SDL_AudioDeviceID devid_in = 0;  
  16. static SDL_AudioDeviceID devid_out = 0;  
  17.   
  18. static void  
  19. loop()  
  20. {  
  21.     SDL_bool please_quit = SDL_FALSE;  
  22.     SDL_Event e;  
  23.   
  24.     while (SDL_PollEvent(&e)) {  
  25.         if (e.type == SDL_QUIT) {  
  26.             please_quit = SDL_TRUE;  
  27.         }  
  28.         else if (e.type == SDL_KEYDOWN) {  
  29.             if (e.key.keysym.sym == SDLK_ESCAPE) {  
  30.                 please_quit = SDL_TRUE;  
  31.             }  
  32.         }  
  33.         else if (e.type == SDL_MOUSEBUTTONDOWN) {  
  34.             if (e.button.button == 1) {  
  35.                 SDL_PauseAudioDevice(devid_out, SDL_TRUE);  
  36.                 SDL_PauseAudioDevice(devid_in, SDL_FALSE);  
  37.             }  
  38.         }  
  39.         else if (e.type == SDL_MOUSEBUTTONUP) {  
  40.             if (e.button.button == 1) {  
  41.                 SDL_PauseAudioDevice(devid_in, SDL_TRUE);  
  42.                 SDL_PauseAudioDevice(devid_out, SDL_FALSE);  
  43.             }  
  44.         }  
  45.     }  
  46.   
  47.     if (SDL_GetAudioDeviceStatus(devid_in) == SDL_AUDIO_PLAYING) {  
  48.         SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);  
  49.     }  
  50.     else {  
  51.         SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);  
  52.     }  
  53.     SDL_RenderClear(renderer);  
  54.     SDL_RenderPresent(renderer);  
  55.   
  56.     if (please_quit) {  
  57.         /* stop playing back, quit. */  
  58.         SDL_Log("Shutting down.\n");  
  59.         SDL_PauseAudioDevice(devid_in, 1);  
  60.         SDL_CloseAudioDevice(devid_in);  
  61.         SDL_PauseAudioDevice(devid_out, 1);  
  62.         SDL_CloseAudioDevice(devid_out);  
  63.         SDL_DestroyRenderer(renderer);  
  64.         SDL_DestroyWindow(window);  
  65.         SDL_Quit();  
  66. #ifdef __EMSCRIPTEN__  
  67.         emscripten_cancel_main_loop();  
  68. #endif  
  69.         exit(0);  
  70.     }  
  71.   
  72.     /* Note that it would be easier to just have a one-line function that 
  73.     calls SDL_QueueAudio() as a capture device callback, but we're 
  74.     trying to test the API, so we use SDL_DequeueAudio() here. */  
  75.     while (SDL_TRUE) {  
  76.         Uint8 buf[1024];  
  77.         const Uint32 br = SDL_DequeueAudio(devid_in, buf, sizeof(buf));  
  78.         SDL_QueueAudio(devid_out, buf, br);  
  79.         if (br < sizeof(buf)) {  
  80.             break;  
  81.         }  
  82.     }  
  83. }  
  84.   
  85. int  
  86. main(int argc, charchar **argv)  
  87. {  
  88.     /* (argv[1] == NULL means "open default device.") */  
  89.     const charchar *devname = argv[1];  
  90.     SDL_AudioSpec wanted;  
  91.     int devcount;  
  92.     int i;  
  93.   
  94.     /* Enable standard application logging */  
  95.     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);  
  96.   
  97.     /* Load the SDL library */  
  98.     if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {  
  99.         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());  
  100.         return (1);  
  101.     }  
  102.   
  103.     window = SDL_CreateWindow("testaudiocapture", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 320, 240, 0);  
  104.     renderer = SDL_CreateRenderer(window, -1, 0);  
  105.     SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);  
  106.     SDL_RenderClear(renderer);  
  107.     SDL_RenderPresent(renderer);  
  108.   
  109.     SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver());  
  110.   
  111.     devcount = SDL_GetNumAudioDevices(SDL_TRUE);  
  112.     for (i = 0; i < devcount; i++) {  
  113.         SDL_Log(" Capture device #%d: '%s'\n", i, SDL_GetAudioDeviceName(i, SDL_TRUE));  
  114.     }  
  115.   
  116.     SDL_zero(wanted);  
  117.     wanted.freq = 44100;  
  118.     wanted.format = AUDIO_F32SYS;  
  119.     wanted.channels = 1;  
  120.     wanted.samples = 4096;  
  121.     wanted.callback = NULL;  
  122.   
  123.     SDL_zero(spec);  
  124.   
  125.     /* DirectSound can fail in some instances if you open the same hardware 
  126.     for both capture and output and didn't open the output end first, 
  127.     according to the docs, so if you're doing something like this, always 
  128.     open your capture devices second in case you land in those bizarre 
  129.     circumstances. */  
  130.   
  131.     SDL_Log("Opening default playback device...\n");  
  132.     devid_out = SDL_OpenAudioDevice(NULL, SDL_FALSE, &wanted, &spec, SDL_AUDIO_ALLOW_ANY_CHANGE);  
  133.     if (!devid_out) {  
  134.         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open an audio device for playback: %s!\n", SDL_GetError());  
  135.         SDL_Quit();  
  136.         exit(1);  
  137.     }  
  138.   
  139.     SDL_Log("Opening capture device %s%s%s...\n",  
  140.         devname ? "'" : "",  
  141.         devname ? devname : "[[default]]",  
  142.         devname ? "'" : "");  
  143.   
  144.     devid_in = SDL_OpenAudioDevice(argv[1], SDL_TRUE, &spec, &spec, 0);  
  145.     if (!devid_in) {  
  146.         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open an audio device for capture: %s!\n", SDL_GetError());  
  147.         SDL_Quit();  
  148.         exit(1);  
  149.     }  
  150.   
  151.     SDL_Log("Ready! Hold down mouse or finger to record!\n");  
  152.   
  153. #ifdef __EMSCRIPTEN__  
  154.     emscripten_set_main_loop(loop, 0, 1);  
  155. #else  
  156.     while (1) { loop(); SDL_Delay(16); }  
  157. #endif  
  158.   
  159.     return 0;  
  160. }  

 

播放wav音频:

    1. // testSDL_AudioLoopWave.cpp : 定义控制台应用程序的入口点。  
    2. //  
    3.   
    4. #include "stdafx.h"  
    5.   
    6. extern "C"{  
    7. #include "include\SDL.h"  
    8. }  
    9.   
    10. struct  
    11. {  
    12.     SDL_AudioSpec spec;  
    13.     Uint8 *sound;               /* Pointer to wave data */  
    14.     Uint32 soundlen;            /* Length of wave data */  
    15.     int soundpos;               /* Current play position */  
    16. } wave;  
    17.   
    18.   
    19. /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */  
    20. static void  
    21. quit(int rc)  
    22. {  
    23.     SDL_Quit();  
    24.     exit(rc);  
    25. }  
    26.   
    27.   
    28. void SDLCALL  
    29. fillerup(voidvoid *unused, Uint8 * stream, int len)  
    30. {  
    31.     Uint8 *waveptr;  
    32.     int waveleft;  
    33.   
    34.     /* Set up the pointers */  
    35.     waveptr = wave.sound + wave.soundpos;  
    36.     waveleft = wave.soundlen - wave.soundpos;  
    37.   
    38.     /* Go! */  
    39.     /*这里有2种情况 
    40.      1.如果waveleft>len,则直接拷贝数据播放 
    41.      2.如果waveleft<=len,则先把剩下的数据拷贝到stream,同时拷贝开头剩下的len-waveleft数据到stream*/  
    42.     while (waveleft <= len) {  
    43.         /*播放完升下的数据*/  
    44.         SDL_memcpy(stream, waveptr, waveleft);  
    45.         stream += waveleft;  
    46.         len -= waveleft;  
    47.   
    48.         /*播放完毕后将指针指向音频数据的开头*/  
    49.         waveptr = wave.sound;  
    50.         waveleft = wave.soundlen;  
    51.         wave.soundpos = 0;  
    52.     }  
    53.     SDL_memcpy(stream, waveptr, len);  
    54.     wave.soundpos += len;  
    55. }  
    56.   
    57. static int done = 0;  
    58. void  
    59. poked(int sig)  
    60. {  
    61.     done = 1;  
    62. }  
    63.   
    64. #ifdef __EMSCRIPTEN__  
    65. void  
    66. loop()  
    67. {  
    68.     if (done || (SDL_GetAudioStatus() != SDL_AUDIO_PLAYING))  
    69.         emscripten_cancel_main_loop();  
    70. }  
    71. #endif  
    72.   
    73. int  
    74. main(int argc, charchar *argv[])  
    75. {  
    76.     int i;  
    77.     char filename[4096];  
    78.   
    79.     /* Enable standard application logging */  
    80.     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);  
    81.   
    82.     /* Load the SDL library */  
    83.     if (SDL_Init(SDL_INIT_AUDIO) < 0) {  
    84.         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());  
    85.         return (1);  
    86.     }  
    87.   
    88.     if (argc > 1) {  
    89.         SDL_strlcpy(filename, argv[1], sizeof(filename));  
    90.     }  
    91.     else {  
    92.         SDL_strlcpy(filename, "sample.wav", sizeof(filename));  
    93.     }  
    94.     /* Load the wave file into memory */  
    95.     /*SDL_LoadWAV这个函数读取wav音频文件后会进行下面操作 
    96.      1.填充wave.spec结构体 
    97.      2.将音频数据填充到wave.sound 
    98.      3.将音频数据长度填到wave.soundlen*/  
    99.     if (SDL_LoadWAV(filename, &wave.spec, &wave.sound, &wave.soundlen) == NULL) {  
    100.         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", filename, SDL_GetError());  
    101.         quit(1);  
    102.     }  
    103.   
    104.     /*播放的时候需要数据时会回调到fillerup获取音频播放数据*/  
    105.     wave.spec.callback = fillerup;  
    106. #if HAVE_SIGNAL_H  
    107.     /* Set the signals */  
    108. #ifdef SIGHUP  
    109.     signal(SIGHUP, poked);  
    110. #endif  
    111.     signal(SIGINT, poked);  
    112. #ifdef SIGQUIT  
    113.     signal(SIGQUIT, poked);  
    114. #endif  
    115.     signal(SIGTERM, poked);  
    116. #endif /* HAVE_SIGNAL_H */  
    117.   
    118.     /* Show the list of available drivers */  
    119.     SDL_Log("Available audio drivers:");  
    120.     for (i = 0; i < SDL_GetNumAudioDrivers(); ++i) {  
    121.         SDL_Log("%i: %s", i, SDL_GetAudioDriver(i));  
    122.     }  
    123.   
    124.     /* Initialize fillerup() variables */  
    125.     if (SDL_OpenAudio(&wave.spec, NULL) < 0) {  
    126.         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open audio: %s\n", SDL_GetError());  
    127.         SDL_FreeWAV(wave.sound);  
    128.         quit(2);  
    129.     }  
    130.   
    131.     SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver());  
    132.   
    133.     /* Let the audio run */  
    134.     /*开始播放*/  
    135.     SDL_PauseAudio(0);  
    136.   
    137. #ifdef __EMSCRIPTEN__  
    138.     emscripten_set_main_loop(loop, 0, 1);  
    139. #else  
    140.     while (!done && (SDL_GetAudioStatus() == SDL_AUDIO_PLAYING))  
    141.         SDL_Delay(1000);  
    142. #endif  
    143.   
    144.     /* Clean up on signal */  
    145.     SDL_CloseAudio();  
    146.     SDL_FreeWAV(wave.sound);  
    147.     SDL_Quit();  
    148.     return (0);  
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值