11 #define BUFFER_COUNT 8
12 #define INJECT_OFFSET 256 /* arbitrary */
15 static struct cdi_audio_device
*audio_device
;
16 static struct cdi_audio_driver
*audio_driver
;
17 static struct cdi_audio_stream
*audio_stream
;
19 static void (*buffer_cb
)(int16_t *data
, size_t samples
);
20 static int current_device_buffer
;
22 static struct cdi_mem_area
*buffers
[BUFFER_COUNT
];
23 static int prebuffered_buffers
;
26 void register_cdi_audio_device(struct cdi_audio_device
*dev
)
28 if (audio_device
|| dev
->record
) {
33 audio_driver
= (struct cdi_audio_driver
*)dev
->dev
.driver
;
34 audio_stream
= cdi_list_get(audio_device
->streams
, 0);
36 if (audio_stream
->sample_format
!= CDI_AUDIO_16SI
) {
41 audio_driver
->set_sample_rate(audio_stream
, 44100);
42 audio_driver
->set_number_of_channels(audio_device
, 2);
43 audio_driver
->set_volume(audio_stream
, 0xff);
46 bool init_audio(void (*callback
)(int16_t *data
, size_t samples
))
52 for (int i
= 0; i
< BUFFER_COUNT
; i
++) {
53 buffers
[i
] = cdi_mem_alloc(audio_stream
->buffer_size
* 2, CDI_MEM_VIRT_ONLY
);
61 static void fetch_buffers(void)
63 int hw_index
= (current_device_buffer
+ prebuffered_buffers
) % audio_stream
->num_buffers
;
65 for (; prebuffered_buffers
< BUFFER_COUNT
; prebuffered_buffers
++) {
66 buffer_cb(buffers
[prebuffered_buffers
]->vaddr
, audio_stream
->buffer_size
);
67 audio_driver
->transfer_data(audio_stream
, hw_index
, buffers
[prebuffered_buffers
], 0);
69 hw_index
= (hw_index
+ 1) % audio_stream
->num_buffers
;
73 void audio_play(bool play
)
79 audio_driver
->change_device_status(audio_device
, play
? CDI_AUDIO_PLAY
: CDI_AUDIO_STOP
);
86 void audio_mute(bool mute
)
88 audio_driver
->set_volume(audio_stream
, mute
? 0x00 : 0xff);
91 void inject_samples(int16_t *data
, size_t count
)
93 cdi_audio_position_t pos
;
94 audio_driver
->get_position(audio_stream
, &pos
);
96 size_t position
= pos
.frame
* 2 + INJECT_OFFSET
;
97 int buffer
= position
/ audio_stream
->buffer_size
;
98 int offset
= position
% audio_stream
->buffer_size
;
100 while (count
&& buffer
< prebuffered_buffers
) {
101 /* I need variables like this all the time but I still don't know a good
102 * way to name them... */
103 size_t this_buffer_count
= audio_stream
->buffer_size
- offset
;
104 if (this_buffer_count
> count
) {
105 this_buffer_count
= count
;
108 int16_t *out
= buffers
[buffer
]->vaddr
;
110 for (size_t i
= 0; i
< this_buffer_count
; i
++) {
111 int val
= out
[i
] + data
[i
];
114 } else if (val
> 0x7fff) {
119 data
+= this_buffer_count
;
123 count
-= this_buffer_count
;
126 int hw_index
= current_device_buffer
;
127 for (int i
= 0; i
< buffer
; i
++) {
128 audio_driver
->transfer_data(audio_stream
, hw_index
, buffers
[i
], 0);
129 hw_index
= (hw_index
+ 1) % audio_stream
->num_buffers
;
133 void cdi_audio_buffer_completed(struct cdi_audio_stream
*stream
, size_t buffer
)
137 buffer
= (buffer
+ 1) % audio_stream
->num_buffers
;
139 cdi_audio_position_t pos
;
140 audio_driver
->get_position(audio_stream
, &pos
);
142 while (current_device_buffer
!= buffer
) {
143 struct cdi_mem_area
*popped
= buffers
[0];
144 memmove(&buffers
[0], &buffers
[1], sizeof(buffers
[0]) * (BUFFER_COUNT
- 1));
145 buffers
[BUFFER_COUNT
- 1] = popped
;
147 current_device_buffer
= (current_device_buffer
+ 1) % audio_stream
->num_buffers
;
149 if (prebuffered_buffers
) {
150 prebuffered_buffers
--;