This document records the Audio Playback Technology of SDL. The version used here is sdl2. In fact, SDL does not provide the video/audio playback function. It only encapsulates the underlying API for video/audio playback. On Windows, SDL encapsulates direct3d APIs for video playback and directsound APIs for audio playback. Because SDL is designed to simplify the development of video and audio playback, it is very easy to Use SDL to play video (YUV/RGB) and audio (PCM) data.
SDL Introduction
SDL (Simple DirectMedia Layer) is an open-source cross-platform multimedia development library written in C language. SDL provides several functions for controlling images, sounds, and outputs, developers can use the same or similar code to develop applications across multiple platforms (such as Linux, windows, and Mac OS X. Currently, SDL is mostly used for developing multimedia applications such as games, simulators, and media players. The following figure shows the purpose of SDL.
SDL is actually not limited to playing audio and video. It divides functions into the following subsystems (subsystems ):
Video (image): image control and thread and event management ).
Audio: Sound Control
Joystick (joystick): Game Joystick Control
CD-ROM (disc drive): disc media control
Windows Management: integrated with windows program design
Event: event-driven processing
In Windows, the relationship between SDL and DirectX is as follows.
SDL |
DirectX |
Sdl_video and sdl_image |
DirectDraw, direct3d |
Sdl_audio and sdl_mixer |
Directsound |
Sdl_joystick and sdl_base |
Directinput |
Sdl_net |
Directplay |
Note: The above content has been introduced in the article "using SDL to play a video". I will repeat it here.
Audio playback process in SDL
The process of playing audio from SDL is very simple and involves the following steps.
1. Initialization
1) initialize SDL.
2) Enable the audio device according to the parameter (sdl_audiospec)
2. Loop playback data
1) play audio data.
2) latency: wait until the playback is complete.
The following describes the process in detail.
1. Initialization
1) initialize SDL.
Use sdl_init () to initialize SDL. This function can determine the subsystem to be activated. The sdl_init () function is defined as follows:
int SDLCALL SDL_Init(Uint32 flags)
Among them, flags can take the following values:
Sdl_init_timer: Timer
Sdl_init_audio: Audio
Sdl_init_video: Video
Sdl_init_joystick: joystick
Sdl_init_haptic: Touch Screen
Sdl_init_gamecontroller: Game Controller
Sdl_init_events: Event
Sdl_init_noparachute: do not capture key signals (this is not understandable)
Sdl_init_everything: contains all the above options
Note the following for sdl_init (): Do not use sdl_init_everything during initialization. In some cases, using sdl_init_everything may cause unpredictable problems. For example, to play pure audio in an MFC application, if sdl_init_everything is used during SDL initialization, the audio will not be heard. Later, we found that the problem was solved only after sdl_init_video was removed.
2) Enable the audio device according to the parameter (sdl_audiospec)
Use sdl_openaudio () to open the audio device. This function requires the input of an sdl_audiospec struct. Dl_openaudio () is defined as follows.
int SDLCALL SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained);
Its parameters are two sdl_audiospec struct. Their meanings:
Desired: The expected parameter.
Obtained: the parameter of the actual audio device. Generally, set it to null.
The structure of sdl_audiospec is defined as follows.
typedef struct SDL_AudioSpec{ int freq; /**< DSP frequency -- samples per second */ SDL_AudioFormat format; /**< Audio data format */ Uint8 channels; /**< Number of channels: 1 mono, 2 stereo */ Uint8 silence; /**< Audio buffer silence value (calculated) */ Uint16 samples; /**< Audio buffer size in samples (power of 2) */ Uint16 padding; /**< Necessary for some compile environments */ Uint32 size; /**< Audio buffer size in bytes (calculated) */ SDL_AudioCallback callback; void *userdata;} SDL_AudioSpec;
It includes audio parameters:
Freq: the sampling rate of audio data. Commonly used include, 44100, etc.
Format: audio data format. Example formats:
Audio_u16sys: Unsigned 16-bit Samples
Audio_s16sys: signed 16-bit Samples
Audio_s32sys: 32-bit integer Samples
Audio_f32sys: 32-bit floating point samples
Channels: number of channels. For example, the single-channel value is 1, and the stereo value is 2.
Silence: Set the mute value.
Samples: the number of samples in the audio buffer, which must be the Npower of 2.
Padding: a parameter considering compatibility.
Size: the size of the audio buffer, in bytes.
Callback: callback function for filling the audio buffer.
Userdata: User-defined data.
Here, we will record the function of filling in the audio buffer. This callback function is called when the audio device needs more data. The format requirements for callback functions are as follows.
void (SDLCALL * SDL_AudioCallback) (void *userdata, Uint8 * stream, int len);
The parameter Meanings of the callback function are as follows.
Userdata: User-defined data in the sdl_audiospec structure, which is generally not required.
Stream: This Pointer Points to the audio buffer to be filled.
Len: the size of the audio buffer (in bytes ).
You can use sdl_mixaudio () in the callback function to complete sound mixing and other work. As we all know, sdl2 and sdl1.x have very different video APIs. However, sdl2 and sdl1.x have identical audio APIs. In the callback function alone, sdl2 has a difference from sdl1.x: In sdl2, you must first use sdl_memset () to set the data in stream to 0.
2. Loop playback data
1) play audio data.
You can use sdl_pauseaudio () to play audio data. Sdl_pauseaudio () is defined as follows.
void SDLCALL SDL_PauseAudio(int pause_on)
When pause_on is set to 0, the audio data can be played. When it is set to 1, it will play the mute value.
2) latency: wait until the playback is complete.
This step is delayed waiting for the audio to be played. Use a latency function like sdl_delay.
The source code is as follows.
/*** Simplest example of sdl2 playing audio (sdl2 playing PCM) * simplest audio play sdl2 (sdl2 play PCM) ** leixiao Li Lei Xiaohua * [email protected] * media University of China/Digital TV technology * Communication University of China/Digital TV technology * http://blog.csdn.net/leixiaohua1020 ** this program uses sdl2 to play PCM audio sample data. SDL is actually an encapsulation of the underlying graph * API (direct3d, OpenGL). It is obviously easy to use to directly call the underlying * API. ** Function call procedure: ** [initialization] * sdl_init (): Initialize SDL. * Sdl_openaudio (): Enable the audio device based on the parameter (stored in sdl_audiospec. ** [Loop playback data] * sdl_pauseaudio (): play audio data. * Sdl_delay (): latency: waiting for the playback to complete. ** This software plays PCM raw audio data using sdl2. * SDL is a wrapper of low-level API (directsound ). * Use SDL is much easier than directly call these low-level API. ** the process is shown as follows: ** [init] * sdl_init (): init SDL. * sdl_openaudio (): opens the audio device with the desired * parameters (in sdl_audiospec ). ** [loop to play data] * sdl_pauseaudio (): play audio. * sdl_dela Y (): Wait for completetion of playback. */# include <stdio. h> # include <tchar. h> extern "C" {# include "SDL/SDL. H "}; // Buffer: // | ------------- | // chunk ------- POS --- Len ----- | static uint8 * audio_chunk; static uint32 audio_len; static uint8 * audio_pos; /* audio callback * the audio function callback takes the following parameters: * stream: a pointer to the audio buffer to be filled * Len: The L Ength (in bytes) of the audio buffer **/void fill_audio (void * udata, uint8 * stream, int Len) {// SDL 2.0sdl _ memset (stream, 0, len); If (audio_len = 0)/* only play if we have data left */return; Len = (LEN> audio_len? Audio_len: Len);/* mix as much data as possible */sdl_mixaudio (stream, audio_pos, Len, sdl_mix_maxvolume); audio_pos + = Len; audio_len-= Len ;} int main (INT argc, char * argv []) {// initif (sdl_init (sdl_init_audio | sdl_init_timer) {printf ("cocould not initialize SDL-% s \ n ", sdl_geterror (); Return-1;} // sdl_audiospecsdl_audiospec wanted_spec; wanted_spec.freq = 44100; wanted_spec.format = audio_s16sys; Wanted_spec.channels = 2; wanted_spec.silence = 0; channels = 1024; wanted_spec.callback = fill_audio; If (sdl_openaudio (& wanted_spec, null) <0) {printf ("can't open audio. \ n "); Return-1;} file * fp = fopen (".. /nocturneno2ineflat_44.1k_s16le.pcm "," RB + "); If (FP = NULL) {printf (" cannot open this file \ n "); Return-1 ;} // For yuv420pint pcm_buffer_size = 4096; char * pcm_buffer = (char *) malloc (pcm_buffer _ Size); int data_count = 0; while (1) {If (fread (pcm_buffer, 1, pcm_buffer_size, FP )! = Pcm_buffer_size) {// loopfseek (FP, 0, seek_set); fread (pcm_buffer, 1, pcm_buffer_size, FP); data_count = 0 ;} printf ("Now playing % 10d bytes data. \ n ", data_count); data_count + = pcm_buffer_size; // set audio buffer (PCM Data) audio_chunk = (uint8 *) pcm_buffer; // audio buffer lengthaudio_len = pcm_buffer_size; audio_pos = audio_chunk; // playsdl_pauseaudio (0); While (audio_len> 0) // wait until finishsdl_delay (1);} return 0 ;}
Running result
Shows the running result. You can hear the music playing sound during running.
Download
The code is in "simplest media play"
SourceForge project: https://sourceforge.net/projects/simplestmediaplay/
Http://download.csdn.net/detail/leixiaohua1020/8054395 (csdn)
The above project contains the use of various APIs (direct3d, OpenGL, GDI, directsound, sdl2) to play multimedia examples. The audio input is PCM sampling data. Output to the sound card of the system. The video input is YUV/RGB pixel data. Output to a display window for playing.
The code of this project allows beginners to quickly learn how to use these APIs to play videos and audios.
The following sub-projects are included:
Simplest_audio_play_directsound: Use directsound to play PCM audio sample data.
Simplest_audio_play_sdl2: Use sdl2 to play PCM audio sample data.
Simplest_video_play_direct3d: Use the direct3d surface to play RGB/YUV video pixel data.
Simplest_video_play_direct3d_texture: Use direct3d texture to play RGB video pixel data.
Simplest_video_play_gdi: Use GDI to play RGB/YUV video pixel data.
Simplest_video_play_opengl: uses OpenGL to play pixel data of RGB/YUV videos.
Simplest_video_play_opengl_texture: use OpenGL texture to play the YUV video pixel data.
Simplest_video_play_sdl2: Use sdl2 to play RGB/YUV video pixel data.
Example 9: sdl2 PCM playback