-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathwav_record.c
132 lines (103 loc) · 4.37 KB
/
wav_record.c
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
#include <stdio.h>
#include <SDL2/SDL.h>
#include <stdbool.h>
// Record some audio, then play it back
#define SECONDS 6
#define CHANNELS 2
typedef struct {
int size;
int play_cursor;
enum Buffer_Type {
PLAY,
RECORD
} buffer_type;
Sint16 *buffer;
} Audio_Data;
void audio_callback(void *userdata, Uint8 *stream, int len);
int main(int argc, char* argv[]){
printf("Start recording audio\n");
// Init SDL
if (SDL_Init(SDL_INIT_AUDIO) < 0) {
printf("SDL init error: %s\n", SDL_GetError());
return 1;
}
int samples_per_second = 44100;
int bytes_per_sample = sizeof(Uint16) * CHANNELS;
int bytes_to_write = samples_per_second * bytes_per_sample * SECONDS;
void *record_buffer = malloc(bytes_to_write);
Sint16 *record_write = (Sint16 *)record_buffer;
Audio_Data record;
record.size = bytes_to_write;
record.play_cursor = 0;
record.buffer_type = RECORD;
record.buffer = record_write;
SDL_AudioSpec record_wanted_spec;
SDL_AudioSpec record_obtained_spec;
record_wanted_spec.freq = samples_per_second;
record_wanted_spec.format = AUDIO_S16;
record_wanted_spec.channels = CHANNELS;
record_wanted_spec.samples = 4096; // SDL buffer sample size (same used for wav files)
record_wanted_spec.callback = audio_callback;
record_wanted_spec.userdata = &record;
// Open the audio device
int iscapture = 1; // We are opening the device for recording so iscapture = 1
int allowed_changes = 0; // See docs for info on what this is for
const char* record_device_name = SDL_GetAudioDeviceName(0, iscapture); // Gets the zero'th capture device name (see docs for more info)
SDL_AudioDeviceID record_device = SDL_OpenAudioDevice(record_device_name, iscapture, &record_wanted_spec, &record_obtained_spec, allowed_changes);
if (record_device == 0) {
printf("SDL_OpenAudioDevice error: %s\n", SDL_GetError());
return 1;
}
// Start recording
SDL_PauseAudioDevice(record_device, 0);
// Wait for SECONDS number of seconds
SDL_Delay(SECONDS * 1000);
// Stop recording
SDL_PauseAudioDevice(record_device, 1);
printf("Recording stopped\n");
Audio_Data play;
void *play_buffer = malloc(bytes_to_write);
Sint16 *play_write = (Sint16 *)play_buffer;
memcpy(play_buffer, record_buffer, bytes_to_write);
play.size = bytes_to_write;
play.play_cursor = 0;
play.buffer_type = PLAY;
play.buffer = play_write;
SDL_AudioSpec play_wanted_spec;
SDL_AudioSpec play_obtained_spec;
play_wanted_spec = record_wanted_spec; // play and record specs are the same but just point to different userdata
play_wanted_spec.userdata = &play;
// Open the audio device for playing
iscapture = 0; // We are not opening the device for recording so iscapture = 0
const char* play_device_name = SDL_GetAudioDeviceName(0, iscapture); // Gets the zero'th non-capture device name (see docs for more info)
SDL_AudioDeviceID play_device = SDL_OpenAudioDevice(play_device_name, iscapture, &play_wanted_spec, &play_obtained_spec, allowed_changes);
if (play_device == 0) {
printf("SDL_OpenAudioDevice error: %s\n", SDL_GetError());
return 1;
}
// Start playing
printf("Start Playing recorded audio\n");
SDL_PauseAudioDevice(play_device, 0);
// Wait for SECONDS number of seconds
SDL_Delay(SECONDS * 1000);
// Shut everything down
SDL_CloseAudioDevice(record_device);
SDL_CloseAudioDevice(play_device);
free(record.buffer);
free(play.buffer);
SDL_Quit();
}
// This is our custom Audio callback function, SDL will call this function when
// it is ready for more data (audio) in or out of the audio device
void audio_callback(void *userdata, Uint8 *stream, int len) {
// Cast the userdata to Audio_Data so we can use it
Audio_Data *audio_data = (Audio_Data *) userdata;
// Return if SDL asks for data past the end of the buffer
if (audio_data->play_cursor + len > audio_data->size) return;
// Copy data from the stream on record and copy data to the stream on play
if (audio_data->buffer_type == RECORD)
memcpy(((Uint8 *) audio_data->buffer + audio_data->play_cursor), stream, len);
else if (audio_data->buffer_type == PLAY)
memcpy(stream, ((Uint8 *) audio_data->buffer + audio_data->play_cursor), len);
audio_data->play_cursor += len;
}