aboutsummaryrefslogtreecommitdiff
path: root/src/libjin/audio/SDL/sdl_audio.cpp
blob: 4c4bcc23d6834605d670668c7e2a7b1baf98aa9a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include "../../core/configuration.h"
#if defined(jin_audio) && (jin_audio == jin_audio_sdl)

#include <iostream>

#include "../../math/math.h"
#include "../../utils/log.h"

#include "sdl_audio.h"
#include "sdl_source.h"

using namespace JinEngine::Math;

namespace JinEngine
{
    namespace Audio
    {
        namespace SDL
        {

            /* עcallbackƵ̵߳ */
            static void defaultCallback(void *userdata, Uint8 *stream, int size)
            {
                static SDLAudio* audio = static_cast<SDLAudio*>(userdata);
                if (!audio->goOnProcess())
                    return;
                audio->lock();
                audio->processCommands();
                audio->processSources(stream, size);
                audio->processBuffer(stream, size);
                audio->unlock();
            }

            /*call only once*/ bool SDLAudio::startSystem(const SettingBase* s)
            {
                jin_log_info("Initialize audio system.");

                if (SDL_Init(SDL_INIT_AUDIO) < 0)
                    return false;

                SDL_AudioSpec spec;
                Setting* setting = (Setting*)s;
                if (setting == nullptr)
                    return false;

                unsigned int samplerate = setting->samplerate;
                unsigned int samples = clamp<int>(setting->samples, 1, setting->samplerate);

                spec.freq = samplerate;        // ÿsample,õ 11025, 22050, 44100 and 48000 Hz. 
                spec.format = AUDIO_S16SYS;      // signed 16-bit samples in native byte order
                spec.channels = SDLAUDIO_CHANNELS; // 
                spec.samples = samples;           // ÿβʱһã=setting->samplerateÿֻ1
                spec.userdata = this;
                spec.callback = defaultCallback;

                audioDevice = SDL_OpenAudioDevice(NULL, 0, &spec, NULL, 0);
                if (audioDevice == 0)
                    return false;
                /* start audio */
                SDL_PauseAudioDevice(audioDevice, 0);
                return true;
            }

            /*call only once*/ void SDLAudio::quitSystem()
            {
                jin_log_info("Quit audio system.");
                SDL_CloseAudio();
            }

            void SDLAudio::lock()
            {
                SDL_LockAudioDevice(audioDevice);
            }

            void SDLAudio::unlock()
            {
                SDL_UnlockAudioDevice(audioDevice);
            }

            bool SDLAudio::goOnProcess()
            {
                if (state == SDLAudio::State::STOP)
                {
                    SDLSourceManager::get()->removeAllSource();
                    pause();
                    return false;
                }
                else if (state == SDLAudio::State::PAUSE)
                    return false;
                else
                    return true;
            }

            void SDLAudio::processCommands()
            {
                SDLSourceManager::get()->processCommands();
            }

            void SDLAudio::processSources(void* buffer, size_t len)
            {
                SDLSourceManager::get()->processSources(buffer, len);
            }

            void SDLAudio::processBuffer(void* buff, size_t len)
            {
                short* buffer = (short*)buff;
                int samples = (len / SDLAUDIO_BYTEDEPTH) >> 1; // ˫
                const char L = 0, R = 1;
                for (int i = 0; i < samples; ++i)
                {
                    short* clip = buffer + (i << 1);
                    clip[L] *= volume;
                    clip[R] *= volume;
                }
            }

            void SDLAudio::play()
            {
                state = State::PLAY;
            }

            void SDLAudio::stop()
            {
                state = State::STOP;
            }

            void SDLAudio::pause()
            {
                state = State::PAUSE;
            }

            void SDLAudio::resume()
            {
                state = State::PLAY;
            }

            void SDLAudio::setVolume(float volume)
            {
                this->volume = clamp(volume, 0.0f, 1.0f);
            }

        } // namespace SDL
    } // namespace Audio
} // namespace JinEngine

#endif // (jin_audio) && (jin_audio == jin_audio_sdl)