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
|
#include <sys/ioctl.h>
#include <stdint.h>
#include <stdbool.h>
#include <fcntl.h>
#include <unistd.h>
#include <SDL/SDL.h>
#include "sound_output.h"
#define UNDERRUN_THRESHOLD 0.75
static int32_t BUFFSIZE;
static uint8_t *buffer;
static uint32_t buf_read_pos = 0;
static uint32_t buf_write_pos = 0;
static int32_t buffered_bytes = 0;
static int32_t sdl_read_buffer(uint8_t* data, int32_t len)
{
if (buffered_bytes >= len)
{
if(buf_read_pos + len <= BUFFSIZE )
{
memcpy(data, buffer + buf_read_pos, len);
}
else
{
int32_t tail = BUFFSIZE - buf_read_pos;
memcpy(data, buffer + buf_read_pos, tail);
memcpy(data + tail, buffer, len - tail);
}
buf_read_pos = (buf_read_pos + len) % BUFFSIZE;
buffered_bytes -= len;
}
return len;
}
static void sdl_write_buffer(uint8_t* data, int32_t len)
{
SDL_LockAudio();
for(uint32_t i = 0; i < len; i += 4)
{
while (buffered_bytes == BUFFSIZE) {
SDL_UnlockAudio();
usleep(1000);
SDL_LockAudio();
}
*(int32_t*)((char*)(buffer + buf_write_pos)) = *(int32_t*)((char*)(data + i));
//memcpy(buffer + buf_write_pos, data + i, 4);
buf_write_pos = (buf_write_pos + 4) % BUFFSIZE;
buffered_bytes += 4;
}
SDL_UnlockAudio();
}
void sdl_callback(void *unused, uint8_t *stream, int32_t len)
{
sdl_read_buffer((uint8_t *)stream, len);
}
uint32_t Audio_Init()
{
SDL_AudioSpec aspec, obtained;
BUFFSIZE = (SOUND_SAMPLES_SIZE * 2 * 2) * 8;
buffer = (uint8_t *) malloc(BUFFSIZE);
/* Add some silence to the buffer */
buffered_bytes = 0;
buf_read_pos = 0;
buf_write_pos = 0;
aspec.format = AUDIO_S16SYS;
aspec.freq = SOUND_OUTPUT_FREQUENCY;
aspec.channels = 2;
aspec.samples = SOUND_SAMPLES_SIZE;
aspec.callback = (sdl_callback);
aspec.userdata = NULL;
/* initialize the SDL Audio system */
if (SDL_InitSubSystem (SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE))
{
printf("SDL: Initializing of SDL Audio failed: %s.\n", SDL_GetError());
return 1;
}
/* Open the audio device and start playing sound! */
if(SDL_OpenAudio(&aspec, &obtained) < 0)
{
printf("SDL: Unable to open audio: %s\n", SDL_GetError());
return 1;
}
SDL_PauseAudio(0);
return 0;
}
void Audio_Write(int16_t* restrict buffer, uint32_t buffer_size)
{
sdl_write_buffer(buffer, buffer_size * 4);
}
bool Audio_Underrun_Likely() {
bool underrun_likely = false;
SDL_LockAudio();
underrun_likely = buffered_bytes < BUFFSIZE * UNDERRUN_THRESHOLD;
SDL_UnlockAudio();
return underrun_likely;
}
void Audio_Close()
{
SDL_PauseAudio(1);
SDL_CloseAudio();
SDL_QuitSubSystem(SDL_INIT_AUDIO);
buffer = NULL;
}
|