#include "muxer.h" #include #include #include #include #include #define SAMPLE_RATE (44100) #define DELAY_IN_SECS (0.075) #define GAIN (1.0) #define FEEDBACK (0.2) #define DRY (1.0) #define WET (0.5) const int delaySize = SAMPLE_RATE * DELAY_IN_SECS; class Sound { public: Sound(const char* filename, float vol); ~Sound(); float* ptr; unsigned long pos; unsigned long len; float vol; }; struct Muxer { std::list playing; PaStream* stream; float* delay; unsigned long delayPos; }; inline void dealWithPaError(PaError err) { if (err != paNoError) { printf("PortAudio error: %s\n", Pa_GetErrorText(err)); exit(-1); } } int paMuxerCallback(const void*, void* outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo*, PaStreamCallbackFlags, void* userData) { Muxer* muxer = (Muxer*) userData; float* out = (float*) outputBuffer; for (unsigned long i = 0; iplaying) { if (sound.pos < sound.len) { in += sound.ptr[sound.pos++] * sound.vol; } } if (in > 1) in = 1; if (in < -1) in = -1; float sample = muxer->delay[muxer->delayPos] * GAIN; muxer->delay[muxer->delayPos] = in + (muxer->delay[muxer->delayPos] * FEEDBACK); muxer->delayPos++; if (muxer->delayPos > delaySize) muxer->delayPos = 0; *out++ = (in * DRY) + (sample * WET); } return 0; } static Muxer* muxer; void initMuxer() { muxer = new Muxer(); dealWithPaError(Pa_Initialize()); dealWithPaError(Pa_OpenDefaultStream(&muxer->stream, 0, 1, paFloat32, SAMPLE_RATE, paFramesPerBufferUnspecified, paMuxerCallback, muxer)); dealWithPaError(Pa_StartStream(muxer->stream)); muxer->delay = (float*) calloc(delaySize, sizeof(float)); } void destroyMuxer() { dealWithPaError(Pa_AbortStream(muxer->stream)); dealWithPaError(Pa_CloseStream(muxer->stream)); dealWithPaError(Pa_Terminate()); free(muxer->delay); delete muxer; muxer = 0; } void playSound(const char* filename, float vol) { // First, clear out any sounds that have finished playing muxer->playing.remove_if([] (Sound& value) { return value.pos >= value.len; }); // Then, add the new sound muxer->playing.emplace_back(filename, vol); } Sound::Sound(const char* filename, float vol) { SF_INFO info; SNDFILE* file = sf_open(filename, SFM_READ, &info); if (file == nullptr) { printf("LibSndFile error: %s\n", sf_strerror(file)); exit(-1); } ptr = (float*) malloc(info.frames * info.channels * sizeof(float)); len = info.frames * info.channels; pos = 0; this->vol = vol; sf_readf_float(file, ptr, info.frames); sf_close(file); } Sound::~Sound() { free(ptr); } apedit/src/frame.h?id=dc0f0d6fa178403080658887af3ca1a6c0e41188'>plain) (blame)
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