aboutsummaryrefslogtreecommitdiff
path: root/src/libjin/audio/sdl/source.h
blob: 900568f161981d15e4a192f5ae148e6e11c19cfb (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
#ifndef __JIN_SOURCE_SDL_H
#define __JIN_SOURCE_SDL_H

#include <vector>
#include <queue>
#include <stack>
#include <exception>

#include "../source.h"

namespace jin
{
namespace audio
{

    typedef struct SDLSourceCommand;

    class SDLSource : public Source
    {

    public: 

        ~SDLSource();

        static SDLSource* createSource(SourceType format, const char* file);
        static SDLSource* createSource(SourceType format, void* mem, size_t size);

        /* ISource interface */
        void play() override;
        void stop() override;
        void pause() override;
        void resume() override;
        void rewind() override;
        bool isStopped() const override;
        bool isPaused() const override;
        void setPitch(float pitch) override;
        // Ͻ
        void setVolume(float volume) override;
        bool setLoop(bool loop) override;
        void setRate(float rate) override;

    private:

        SDLSource();

        friend class SDLSourceManager;

        void loadWAV(void* mem, int size);
        void loadOGG(void* mem, int size);

        inline bool is(int state) const { return (status.state & state) == state; }

        struct
        {
            const void* data;       // Ƶ
            int size;               // dataֽڳ
            const void* end;        // dataβ = (unsigned char*)data + size
            int rate;               // Ƶ
            unsigned char bitdepth; // ÿsampleıس
            int samples;            // sample = size / (bitdepth / 8)
            unsigned char channel;  // channel12
            char silence;           // 0
        } raw;

        /* Procedure controller variable */
        struct
        {
            int pos;                // ǰŵλ
            int pitch;              // pitch
            int state;              // ǰ״̬
            bool loop;              // loop or not
            int volume;             // 
        } status;

    };

    class SDLSourceManager
    {
    
    public:

        static SDLSourceManager* get();

        /* Process function */
        static void processCommands();
        static void processSources(Uint8* buffer, int len);

    private:

        friend class SDLSource;

        static void removeSource(SDLSource* source);
        static void pushSource(SDLSource* source);
        static SDLSourceCommand* getCommand();
        static void pushCommand(SDLSourceCommand* cmd);
        static void collectCommand(SDLSourceCommand* cmd);

        static SDLSourceManager* manager;

        static std::queue<SDLSourceCommand*> commands;
        static std::stack<SDLSourceCommand*> commandsPool;
        static std::vector<SDLSource*> sources;            // processing sources

    };

    class SourceException : public std::exception
    {
        const char * what() const throw ()
        {
            return "Load Source Exception";
        }
    };

}
}

#endif