22
33#include <assert.h> // for assert()
44#include <math.h> // for llround()
5+ #include <stdbool.h> // for bool, true, false
6+
57#include <portaudio.h>
68#include <pa_ringbuffer.h>
7- #include "rtmixer.h"
89
9- frame_t get_offset (PaTime time , struct action * action , struct state * state )
10- {
11- frame_t offset = 0 ;
12- if (action -> done_frames == 0 )
13- {
14- PaTime diff = action -> requested_time - time ;
15- if (diff > 0 )
16- {
17- offset = (frame_t )llround (diff * state -> samplerate );
18- // Re-calculate "diff" to propagate rounding errors
19- action -> actual_time = time + (double )offset / state -> samplerate ;
20- }
21- else
22- {
23- // We are too late!
24- action -> actual_time = time ;
25- }
26- }
27- return offset ;
28- }
10+ #include "rtmixer.h"
2911
3012int callback (const void * input , void * output , frame_t frameCount
3113 , const PaStreamCallbackTimeInfo * timeInfo , PaStreamCallbackFlags statusFlags
@@ -44,8 +26,9 @@ int callback(const void* input, void* output, frame_t frameCount
4426
4527 // TODO: check if main thread is still running?
4628
47- struct action * action = NULL ;
48- while (PaUtil_ReadRingBuffer (state -> action_q , & action , 1 ))
29+ for (struct action * action = NULL
30+ ; PaUtil_ReadRingBuffer (state -> action_q , & action , 1 )
31+ ;)
4932 {
5033 // TODO: check action type, remove things if necessary
5134
@@ -54,36 +37,79 @@ int callback(const void* input, void* output, frame_t frameCount
5437 state -> actions = action ;
5538 }
5639
57- action = state -> actions ;
58- while (action )
40+ for (struct action * * actionaddr = & (state -> actions )
41+ ; * actionaddr
42+ ; actionaddr = & ((* actionaddr )-> next ))
5943 {
60- switch (action -> actiontype )
44+ struct action * const action = * actionaddr ;
45+ const bool playing = action -> actiontype == PLAY_BUFFER
46+ || action -> actiontype == PLAY_RINGBUFFER ;
47+ const bool recording = action -> actiontype == RECORD_BUFFER
48+ || action -> actiontype == RECORD_RINGBUFFER ;
49+ const bool using_buffer = action -> actiontype == PLAY_BUFFER
50+ || action -> actiontype == RECORD_BUFFER ;
51+ const bool using_ringbuffer = action -> actiontype == PLAY_RINGBUFFER
52+ || action -> actiontype == RECORD_RINGBUFFER ;
53+ PaTime io_time = 0 ;
54+ if (playing )
6155 {
62- case PLAY_BUFFER :
56+ io_time = timeInfo -> outputBufferDacTime ;
57+ }
58+ if (recording )
59+ {
60+ io_time = timeInfo -> inputBufferAdcTime ;
61+ }
62+
63+ frame_t offset = 0 ;
64+ if (action -> done_frames == 0 )
65+ {
66+ PaTime diff = action -> requested_time - io_time ;
67+ if (diff > 0 )
6368 {
64- frame_t offset = get_offset (timeInfo -> outputBufferDacTime ,
65- action , state );
69+ offset = (frame_t )llround (diff * state -> samplerate );
6670 if (offset >= frameCount )
6771 {
6872 // We are too early!
69- goto next_action ;
73+ continue ;
7074 }
71- frame_t frames = action -> total_frames - action -> done_frames ;
72- if (frameCount < frames )
73- {
74- frames = frameCount ;
75- }
76- float * target = (float * )output ;
75+ // Re-calculate "diff" to propagate rounding errors
76+ action -> actual_time = io_time + (double )offset / state -> samplerate ;
77+ }
78+ else
79+ {
80+ // We are too late!
81+ action -> actual_time = io_time ;
82+ }
83+ }
7784
78- if (frames + offset > frameCount )
79- {
80- assert (frameCount > offset );
81- frames = frameCount - offset ;
82- }
83- target += offset * state -> output_channels ;
85+ frame_t frames = 0 ;
86+ float * target = NULL ;
87+ float * source = NULL ;
8488
85- float * source = action -> buffer ;
86- source += action -> done_frames * action -> channels ;
89+ if (playing )
90+ {
91+ target = (float * )output + offset * state -> output_channels ;
92+ }
93+ else if (recording )
94+ {
95+ source = (float * )input + offset * state -> input_channels ;
96+ }
97+
98+ if (using_buffer )
99+ {
100+ frames = action -> total_frames - action -> done_frames ;
101+ if (frameCount < frames )
102+ {
103+ frames = frameCount ;
104+ }
105+ if (frames + offset > frameCount )
106+ {
107+ assert (frameCount > offset );
108+ frames = frameCount - offset ;
109+ }
110+ if (playing )
111+ {
112+ float * source = action -> buffer + action -> done_frames * action -> channels ;
87113 action -> done_frames += frames ;
88114 while (frames -- )
89115 {
@@ -93,30 +119,36 @@ int callback(const void* input, void* output, frame_t frameCount
93119 }
94120 target += state -> output_channels ;
95121 }
96- if (action -> done_frames == action -> total_frames )
122+ }
123+ else if (recording )
124+ {
125+ float * target = action -> buffer + action -> done_frames * action -> channels ;
126+ action -> done_frames += frames ;
127+ while (frames -- )
97128 {
98- // TODO: stop playback, discard action struct
129+ for (frame_t c = 0 ; c < action -> channels ; c ++ )
130+ {
131+ * target ++ = source [action -> mapping [c ] - 1 ];
132+ }
133+ source += state -> input_channels ;
99134 }
100- break ;
101135 }
102- case PLAY_RINGBUFFER :
136+ if ( action -> done_frames == action -> total_frames )
103137 {
104- // TODO: continue to ignore action->total_frames?
138+ // TODO: stop playback/recording, discard action struct
139+ }
140+ }
141+ else if (using_ringbuffer )
142+ {
143+ // TODO: continue to ignore action->total_frames?
105144
106- frame_t offset = get_offset (timeInfo -> outputBufferDacTime ,
107- action , state );
108- if (offset >= frameCount )
109- {
110- // We are too early!
111- goto next_action ;
112- }
113- float * target = (float * )output ;
114- target += offset * state -> output_channels ;
115- float * block1 = NULL ;
116- float * block2 = NULL ;
117- ring_buffer_size_t size1 = 0 ;
118- ring_buffer_size_t size2 = 0 ;
145+ float * block1 = NULL ;
146+ float * block2 = NULL ;
147+ ring_buffer_size_t size1 = 0 ;
148+ ring_buffer_size_t size2 = 0 ;
119149
150+ if (playing )
151+ {
120152 ring_buffer_size_t read_elements = PaUtil_GetRingBufferReadRegions (
121153 action -> ringbuffer , (ring_buffer_size_t )(frameCount - offset ),
122154 (void * * )& block1 , & size1 , (void * * )& block2 , & size2 );
@@ -141,66 +173,9 @@ int callback(const void* input, void* output, frame_t frameCount
141173 PaUtil_AdvanceRingBufferReadIndex (action -> ringbuffer , read_elements );
142174
143175 // TODO: if ringbuffer is empty, stop playback, discard action struct
144- break ;
145176 }
146- case RECORD_BUFFER :
177+ else if ( recording )
147178 {
148- frame_t offset = get_offset (timeInfo -> inputBufferAdcTime ,
149- action , state );
150- if (offset >= frameCount )
151- {
152- // We are too early!
153- goto next_action ;
154- }
155- frame_t frames = action -> total_frames - action -> done_frames ;
156- if (frameCount < frames )
157- {
158- frames = frameCount ;
159- }
160- float * source = (float * )input ;
161-
162- if (frames + offset > frameCount )
163- {
164- assert (frameCount > offset );
165- frames = frameCount - offset ;
166- }
167- source += offset * state -> input_channels ;
168-
169- float * target = action -> buffer ;
170- target += action -> done_frames * action -> channels ;
171- action -> done_frames += frames ;
172- while (frames -- )
173- {
174- for (frame_t c = 0 ; c < action -> channels ; c ++ )
175- {
176- * target ++ = source [action -> mapping [c ] - 1 ];
177- }
178- source += state -> input_channels ;
179- }
180- if (action -> done_frames == action -> total_frames )
181- {
182- // TODO: stop recording, discard action struct
183- }
184- break ;
185- }
186- case RECORD_RINGBUFFER :
187- {
188- // TODO: continue to ignore action->total_frames?
189-
190- frame_t offset = get_offset (timeInfo -> inputBufferAdcTime ,
191- action , state );
192- if (offset >= frameCount )
193- {
194- // We are too early!
195- goto next_action ;
196- }
197- float * source = (float * )input ;
198- source += offset * state -> input_channels ;
199- float * block1 = NULL ;
200- float * block2 = NULL ;
201- ring_buffer_size_t size1 = 0 ;
202- ring_buffer_size_t size2 = 0 ;
203-
204179 ring_buffer_size_t written = PaUtil_GetRingBufferWriteRegions (
205180 action -> ringbuffer , (ring_buffer_size_t )(frameCount - offset ),
206181 (void * * )& block1 , & size1 , (void * * )& block2 , & size2 );
@@ -224,16 +199,9 @@ int callback(const void* input, void* output, frame_t frameCount
224199 action -> done_frames += (frame_t )written ;
225200 PaUtil_AdvanceRingBufferWriteIndex (action -> ringbuffer , written );
226201
227- // TODO: if ringbuffer is empty, stop playback, discard action struct
228- break ;
202+ // TODO: if ringbuffer is empty, stop recording, discard action struct
229203 }
230- default :
231- ;
232- // TODO: error!
233204 }
234- next_action :
235- action = action -> next ;
236205 }
237-
238206 return paContinue ;
239207}
0 commit comments