1 /*
2 * Allegro audio recording
3 */
4
5 #include "allegro5/allegro_audio.h"
6 #include "allegro5/internal/aintern_audio.h"
7 #include "allegro5/internal/aintern_audio_cfg.h"
8 #include "allegro5/internal/aintern.h"
9
10 ALLEGRO_DEBUG_CHANNEL("audio")
11
12 ALLEGRO_STATIC_ASSERT(recorder,
13 sizeof(ALLEGRO_AUDIO_RECORDER_EVENT) <= sizeof(ALLEGRO_EVENT));
14
15
16 /* Function: al_create_audio_recorder
17 */
al_create_audio_recorder(size_t fragment_count,unsigned int samples,unsigned int frequency,ALLEGRO_AUDIO_DEPTH depth,ALLEGRO_CHANNEL_CONF chan_conf)18 ALLEGRO_AUDIO_RECORDER *al_create_audio_recorder(size_t fragment_count,
19 unsigned int samples, unsigned int frequency,
20 ALLEGRO_AUDIO_DEPTH depth, ALLEGRO_CHANNEL_CONF chan_conf)
21 {
22 size_t i;
23
24 ALLEGRO_AUDIO_RECORDER *r;
25 ASSERT(_al_kcm_driver);
26
27 if (!_al_kcm_driver->allocate_recorder) {
28 ALLEGRO_ERROR("Audio driver does not support recording.\n");
29 return false;
30 }
31
32 r = al_calloc(1, sizeof(*r));
33 if (!r) {
34 ALLEGRO_ERROR("Unable to allocate memory for ALLEGRO_AUDIO_RECORDER\n");
35 return false;
36 }
37
38 r->fragment_count = fragment_count;
39 r->samples = samples;
40 r->frequency = frequency,
41 r->depth = depth;
42 r->chan_conf = chan_conf;
43
44 r->sample_size = al_get_channel_count(chan_conf) * al_get_audio_depth_size(depth);
45
46 r->fragments = al_malloc(r->fragment_count * sizeof(uint8_t *));
47 if (!r->fragments) {
48 al_free(r);
49 ALLEGRO_ERROR("Unable to allocate memory for ALLEGRO_AUDIO_RECORDER fragments\n");
50 return false;
51 }
52
53 r->fragment_size = r->samples * r->sample_size;
54 for (i = 0; i < fragment_count; ++i) {
55 r->fragments[i] = al_malloc(r->fragment_size);
56 if (!r->fragments[i]) {
57 size_t j;
58 for (j = 0; j < i; ++j) {
59 al_free(r->fragments[j]);
60 }
61 al_free(r->fragments);
62
63 ALLEGRO_ERROR("Unable to allocate memory for ALLEGRO_AUDIO_RECORDER fragments\n");
64 return false;
65 }
66 }
67
68 if (_al_kcm_driver->allocate_recorder(r)) {
69 ALLEGRO_ERROR("Failed to allocate recorder from driver\n");
70 return false;
71 }
72
73 r->is_recording = false;
74 r->mutex = al_create_mutex();
75 r->cond = al_create_cond();
76
77 al_init_user_event_source(&r->source);
78
79 if (r->thread) {
80 /* the driver should have created a thread */
81 al_start_thread(r->thread);
82 }
83
84 return r;
85 };
86
87 /* Function: al_start_audio_recorder
88 */
al_start_audio_recorder(ALLEGRO_AUDIO_RECORDER * r)89 bool al_start_audio_recorder(ALLEGRO_AUDIO_RECORDER *r)
90 {
91 ALLEGRO_ASSERT(r);
92
93 al_lock_mutex(r->mutex);
94 r->is_recording = true;
95 al_signal_cond(r->cond);
96 al_unlock_mutex(r->mutex);
97
98 return true;
99 }
100
101 /* Function: al_stop_audio_recorder
102 */
al_stop_audio_recorder(ALLEGRO_AUDIO_RECORDER * r)103 void al_stop_audio_recorder(ALLEGRO_AUDIO_RECORDER *r)
104 {
105 al_lock_mutex(r->mutex);
106 if (r->is_recording) {
107 r->is_recording = false;
108 al_signal_cond(r->cond);
109 }
110 al_unlock_mutex(r->mutex);
111 }
112
113 /* Function: al_is_audio_recorder_recording
114 */
al_is_audio_recorder_recording(ALLEGRO_AUDIO_RECORDER * r)115 bool al_is_audio_recorder_recording(ALLEGRO_AUDIO_RECORDER *r)
116 {
117 bool is_recording;
118
119 al_lock_mutex(r->mutex);
120 is_recording = r->is_recording;
121 al_unlock_mutex(r->mutex);
122
123 return is_recording;
124 }
125
126 /* Function: al_get_audio_recorder_event
127 */
al_get_audio_recorder_event(ALLEGRO_EVENT * event)128 ALLEGRO_AUDIO_RECORDER_EVENT *al_get_audio_recorder_event(ALLEGRO_EVENT *event)
129 {
130 ASSERT(event->any.type == ALLEGRO_EVENT_AUDIO_RECORDER_FRAGMENT);
131 return (ALLEGRO_AUDIO_RECORDER_EVENT *) event;
132 }
133
134 /* Function: al_get_audio_recorder_event_source
135 */
al_get_audio_recorder_event_source(ALLEGRO_AUDIO_RECORDER * r)136 ALLEGRO_EVENT_SOURCE *al_get_audio_recorder_event_source(ALLEGRO_AUDIO_RECORDER *r)
137 {
138 return &r->source;
139 }
140
141 /* Function: al_destroy_audio_recorder
142 */
al_destroy_audio_recorder(ALLEGRO_AUDIO_RECORDER * r)143 void al_destroy_audio_recorder(ALLEGRO_AUDIO_RECORDER *r)
144 {
145 size_t i;
146
147 if (!r)
148 return;
149
150 if (r->thread) {
151 al_set_thread_should_stop(r->thread);
152
153 al_lock_mutex(r->mutex);
154 r->is_recording = false;
155 al_signal_cond(r->cond);
156 al_unlock_mutex(r->mutex);
157
158 al_join_thread(r->thread, NULL);
159 al_destroy_thread(r->thread);
160 }
161
162 if (_al_kcm_driver->deallocate_recorder) {
163 _al_kcm_driver->deallocate_recorder(r);
164 }
165
166 al_destroy_user_event_source(&r->source);
167 al_destroy_mutex(r->mutex);
168 al_destroy_cond(r->cond);
169
170 for (i = 0; i < r->fragment_count; ++i) {
171 al_free(r->fragments[i]);
172 }
173 al_free(r->fragments);
174 al_free(r);
175 }
176