Skip to content

Commit f2235d1

Browse files
committed
Some refactoring
1 parent b26049a commit f2235d1

File tree

1 file changed

+96
-128
lines changed

1 file changed

+96
-128
lines changed

src/rtmixer.c

Lines changed: 96 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,12 @@
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

3012
int 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

Comments
 (0)