Cinnamon audio library
Revision | 3f9332a045583b7c9067a6a24a8b56c625f451d6 (tree) |
---|---|
Zeit | 2019-11-15 17:19:52 |
Autor | AlaskanEmily <emily@alas...> |
Commiter | AlaskanEmily |
Completed OSS backend
@@ -29,7 +29,25 @@ | ||
29 | 29 | CIN_DSP_CONVERT_SAMPLE_INT_TO_INT(COMMON_TYPE, OUT_TYPE, X) |
30 | 30 | #endif |
31 | 31 | |
32 | -static void CIN_DSP_CONVERT_NAME ( | |
32 | +/* Used in the stereo to mono specialization. */ | |
33 | +#define CIN_DSP_STEREO_TO_MONO(IN_PTR, COMMON_VALUE, DEST_PTR) do{ \ | |
34 | + const IN_TYPE *const STM_in_ptr = (IN_PTR); \ | |
35 | + const IN_TYPE STM_in_sample0 = in[0]; \ | |
36 | + const IN_TYPE STM_in_sample1 = in[1]; \ | |
37 | + const COMMON_TYPE STM_common_sample0 = \ | |
38 | + CIN_DSP_CONVERT_SAMPLE_IN_TO_COMMON(STM_in_sample0); \ | |
39 | + const COMMON_TYPE STM_common_sample1 = \ | |
40 | + CIN_DSP_CONVERT_SAMPLE_IN_TO_COMMON(STM_in_sample1); \ | |
41 | + const COMMON_TYPE STM_common_value = (COMMON_VALUE) = \ | |
42 | + (STM_common_sample0 / (COMMON_TYPE)2) + \ | |
43 | + (STM_common_sample1 / (COMMON_TYPE)2); \ | |
44 | + (void)sizeof((COMMON_VALUE)); \ | |
45 | + (DEST_PTR)[0] = \ | |
46 | + CIN_DSP_CONVERT_SAMPLE_COMMON_TO_OUT(STM_common_value); \ | |
47 | + } while(0) | |
48 | + | |
49 | + | |
50 | +static unsigned CIN_DSP_CONVERT_NAME ( | |
33 | 51 | const unsigned num_in_frames, |
34 | 52 | const IN_TYPE *in, |
35 | 53 | OUT_TYPE *out, |
@@ -45,10 +63,14 @@ static void CIN_DSP_CONVERT_NAME ( | ||
45 | 63 | const ldiv_t rate = ldiv(out_sample_rate, in_sample_rate); |
46 | 64 | int at = 0; |
47 | 65 | unsigned i, channel; |
66 | + /* Used for the return value */ | |
67 | + const unsigned char *const original_out = (unsigned char*)out; | |
68 | + | |
69 | + unsigned out_frames = 0; | |
48 | 70 | |
49 | 71 | for(i = 0; i < num_in_frames; i++){ |
50 | - unsigned out_frames = 0; | |
51 | 72 | |
73 | + out_frames = 0; | |
52 | 74 | at -= rate.rem; |
53 | 75 | if(at < 0){ |
54 | 76 | at += in_sample_rate; |
@@ -61,7 +83,14 @@ static void CIN_DSP_CONVERT_NAME ( | ||
61 | 83 | out_frames += rate.quot; |
62 | 84 | if(out_frames != 0){ |
63 | 85 | |
64 | - { | |
86 | + /* Special case for stereo -> mono. Ideally this would NOT be | |
87 | + * checked inside the loop :( | |
88 | + */ | |
89 | + if(in_num_channels == 2 && out_num_channels == 1){ | |
90 | + COMMON_TYPE unused; | |
91 | + CIN_DSP_STEREO_TO_MONO(in, unused, out); | |
92 | + } | |
93 | + else{ | |
65 | 94 | /* Hold on to the final channel we processed, so that we can |
66 | 95 | * paste it over all the remaining channels. |
67 | 96 | */ |
@@ -91,10 +120,45 @@ static void CIN_DSP_CONVERT_NAME ( | ||
91 | 120 | in += in_num_channels; |
92 | 121 | |
93 | 122 | out_frames--; |
94 | - if(out_frames != 0){ | |
123 | + | |
124 | + if(out_frames != 0 && (i + 1) < num_in_frames){ | |
95 | 125 | COMMON_TYPE common_step, common_sample_begin; |
126 | + | |
127 | + /* Special case for stereo -> mono. Ideally this would NOT be | |
128 | + * checked inside the loop :( | |
129 | + */ | |
130 | + if(in_num_channels == 2 && out_num_channels == 1){ | |
131 | + unsigned frame = 0; | |
132 | + /* Get the input samples we will lerp between. */ | |
133 | + COMMON_TYPE common_sample, common_sample_end; | |
134 | + OUT_TYPE unused; | |
135 | + CIN_DSP_STEREO_TO_MONO(in+0, common_sample, &unused); | |
136 | + CIN_DSP_STEREO_TO_MONO(in+2, common_sample_end, &unused); | |
137 | + /* This is slightly lossy with integer common types and | |
138 | + * small steps. */ | |
139 | + common_step = | |
140 | + (common_sample_end - common_sample) / | |
141 | + ((COMMON_TYPE)out_frames); | |
142 | + | |
143 | + while(1){ | |
144 | + out[0] = common_sample; | |
145 | + if(++frame == out_frames) | |
146 | + break; | |
147 | + common_sample += common_step; | |
148 | + out++; | |
149 | + } | |
150 | + | |
151 | + /* This skips the below loops in a way that plays well with | |
152 | + * GCC, clang, and MSVC's optimizers. | |
153 | + */ | |
154 | + channel = out_num_channels; | |
155 | + } | |
156 | + else{ | |
157 | + channel = 0; | |
158 | + } | |
159 | + | |
96 | 160 | /* Process per-channel, since we need to do lerps. */ |
97 | - for(channel = 0; channel < num_common_channels; channel++){ | |
161 | + for(;channel < num_common_channels; channel++){ | |
98 | 162 | /* Get the input samples we will lerp between. */ |
99 | 163 | const IN_TYPE in_sample_start = in[channel]; |
100 | 164 | const IN_TYPE in_sample_end = |
@@ -110,7 +174,8 @@ static void CIN_DSP_CONVERT_NAME ( | ||
110 | 174 | const COMMON_TYPE common_sample_end = |
111 | 175 | CIN_DSP_CONVERT_SAMPLE_IN_TO_COMMON(in_sample_end); |
112 | 176 | |
113 | - OUT_TYPE *dest = out + channel; /* Will be advanced on each frame */ | |
177 | + /* Will be advanced on each frame */ | |
178 | + OUT_TYPE *dest = out + channel; | |
114 | 179 | unsigned frame = 0; |
115 | 180 | |
116 | 181 | /* This is slightly lossy with integer common types and |
@@ -128,9 +193,11 @@ static void CIN_DSP_CONVERT_NAME ( | ||
128 | 193 | } |
129 | 194 | } |
130 | 195 | |
131 | - /* Repeat just the stepping for any remaining channels. */ | |
196 | + /* Copy the last written channel over all remaining channels. | |
197 | + */ | |
132 | 198 | for(; channel < out_num_channels; channel++){ |
133 | - OUT_TYPE *dest = out + channel; /* Will be advanced on each frame */ | |
199 | + /* Will be advanced on each frame */ | |
200 | + OUT_TYPE *dest = out + channel; | |
134 | 201 | COMMON_TYPE common_sample = common_sample_begin; |
135 | 202 | unsigned frame = 0; |
136 | 203 | while(1){ |
@@ -143,12 +210,15 @@ static void CIN_DSP_CONVERT_NAME ( | ||
143 | 210 | } |
144 | 211 | |
145 | 212 | in += in_num_channels; |
146 | - out += out_num_channels * (out_frames + 1); | |
213 | + out += out_num_channels * out_frames; | |
147 | 214 | } |
148 | 215 | } |
149 | 216 | } |
217 | + | |
218 | + return ((unsigned char*)out) - original_out; | |
150 | 219 | } |
151 | 220 | |
221 | +#undef CIN_DSP_STEREO_TO_MONO | |
152 | 222 | #undef COMMON_TYPE |
153 | 223 | #undef OUT_TYPE |
154 | 224 | #undef IN_TYPE |
@@ -97,7 +97,10 @@ static void Cin_DSP_Mix ## TYPE(unsigned num_bytes, \ | ||
97 | 97 | \ |
98 | 98 | switch(num_streams){ \ |
99 | 99 | case 0: return; \ |
100 | - case 1: memmove(out, *in, num_bytes); return; \ | |
100 | + case 1: \ | |
101 | + if(*in != out) \ | |
102 | + memmove(out, *in, num_bytes); \ | |
103 | + return; \ | |
101 | 104 | default: \ |
102 | 105 | case 4: data[3] = in[3]; \ |
103 | 106 | case 3: data[2] = in[2]; \ |
@@ -475,7 +478,7 @@ unsigned Cin_DSP_Convert(unsigned num_bytes, | ||
475 | 478 | void *out_data){ |
476 | 479 | |
477 | 480 | #define CIN_DSP_CONVERT_CALL(IN_TYPE, OUT_TYPE) \ |
478 | - (num_bytes / sizeof(IN_TYPE))/in_format->num_channels, \ | |
481 | + (num_bytes / (sizeof(IN_TYPE) * in_format->num_channels)), \ | |
479 | 482 | (const IN_TYPE *)in_data, \ |
480 | 483 | (OUT_TYPE *)out_data, \ |
481 | 484 | in_format->sample_rate, \ |
@@ -486,39 +489,39 @@ unsigned Cin_DSP_Convert(unsigned num_bytes, | ||
486 | 489 | #define CIN_DSP_CONVERT_1(IN_TYPE) \ |
487 | 490 | switch(out_format->sample_format){ \ |
488 | 491 | case CIN_DSP_FORMAT_S8: \ |
489 | - Cin_DSP_Convert ## IN_TYPE ## S8( \ | |
490 | - CIN_DSP_CONVERT_CALL(IN_TYPE, S8) ); break; \ | |
492 | + return Cin_DSP_Convert ## IN_TYPE ## S8( \ | |
493 | + CIN_DSP_CONVERT_CALL(IN_TYPE, S8) ); \ | |
491 | 494 | case CIN_DSP_FORMAT_S16: \ |
492 | - Cin_DSP_Convert ## IN_TYPE ## S16( \ | |
493 | - CIN_DSP_CONVERT_CALL(IN_TYPE, S16) ); break; \ | |
495 | + return Cin_DSP_Convert ## IN_TYPE ## S16( \ | |
496 | + CIN_DSP_CONVERT_CALL(IN_TYPE, S16) ); \ | |
494 | 497 | case CIN_DSP_FORMAT_S32: \ |
495 | - Cin_DSP_Convert ## IN_TYPE ## S32( \ | |
496 | - CIN_DSP_CONVERT_CALL(IN_TYPE, S32) ); break; \ | |
498 | + return Cin_DSP_Convert ## IN_TYPE ## S32( \ | |
499 | + CIN_DSP_CONVERT_CALL(IN_TYPE, S32) ); \ | |
497 | 500 | case CIN_DSP_FORMAT_FLOAT32: \ |
498 | - Cin_DSP_Convert ## IN_TYPE ## Float32( \ | |
499 | - CIN_DSP_CONVERT_CALL(IN_TYPE, Float32) ); break; \ | |
501 | + return Cin_DSP_Convert ## IN_TYPE ## Float32( \ | |
502 | + CIN_DSP_CONVERT_CALL(IN_TYPE, Float32) ); \ | |
500 | 503 | case CIN_DSP_FORMAT_FLOAT64: \ |
501 | - Cin_DSP_Convert ## IN_TYPE ## Float64( \ | |
502 | - CIN_DSP_CONVERT_CALL(IN_TYPE, Float64) ); break; \ | |
504 | + return Cin_DSP_Convert ## IN_TYPE ## Float64( \ | |
505 | + CIN_DSP_CONVERT_CALL(IN_TYPE, Float64) ); \ | |
503 | 506 | default: \ |
504 | 507 | return 0; \ |
505 | 508 | } |
506 | 509 | |
507 | 510 | switch(in_format->sample_format){ |
508 | 511 | case CIN_DSP_FORMAT_S8: |
509 | - CIN_DSP_CONVERT_1(S8); break; | |
512 | + CIN_DSP_CONVERT_1(S8); | |
510 | 513 | |
511 | 514 | case CIN_DSP_FORMAT_S16: |
512 | - CIN_DSP_CONVERT_1(S16); break; | |
515 | + CIN_DSP_CONVERT_1(S16); | |
513 | 516 | |
514 | 517 | case CIN_DSP_FORMAT_S32: |
515 | - CIN_DSP_CONVERT_1(S32); break; | |
518 | + CIN_DSP_CONVERT_1(S32); | |
516 | 519 | |
517 | 520 | case CIN_DSP_FORMAT_FLOAT32: |
518 | - CIN_DSP_CONVERT_1(Float32); break; | |
521 | + CIN_DSP_CONVERT_1(Float32); | |
519 | 522 | |
520 | 523 | case CIN_DSP_FORMAT_FLOAT64: |
521 | - CIN_DSP_CONVERT_1(Float64); break; | |
524 | + CIN_DSP_CONVERT_1(Float64); | |
522 | 525 | |
523 | 526 | default: |
524 | 527 | return 0; |
@@ -416,7 +416,7 @@ CIN_DSP_CALL(unsigned) Cin_DSP_ConversionSize(unsigned num_bytes, | ||
416 | 416 | * @param in_data Input data to convert |
417 | 417 | * @param out_format Format to convert to |
418 | 418 | * @param out_data Destination buffer. |
419 | - * @return Number of bytes converted. | |
419 | + * @return Number of bytes converted, or 0 on error. | |
420 | 420 | * |
421 | 421 | * @sa Cin_DSP_ConversionSize |
422 | 422 | */ |
@@ -430,6 +430,9 @@ CIN_DSP_CALL(unsigned) Cin_DSP_Convert(unsigned in_bytes, | ||
430 | 430 | /** |
431 | 431 | * @brief Mixes multiple audio buffers of the same format and size. |
432 | 432 | * |
433 | + * Mixing can re-use an input buffer, although if out_data appears in the | |
434 | + * in_data array it MUST be the first element and must only appear once. | |
435 | + * | |
433 | 436 | * @param num_bytes Number of bytes of data to consume |
434 | 437 | * @param format Format of data to consume |
435 | 438 | * @param num_streams Number of streams in @p in_data |
@@ -73,6 +73,7 @@ CIN_PRIVATE(void) Cin_ResampleSound(const struct Cin_Loader *from, | ||
73 | 73 | * You must include cin_soft_loader.h and cin_dsp.h to use this. |
74 | 74 | * This is only a macro to allow us to avoid adding an additional library just |
75 | 75 | * to glue together SoftLoader and MixerSound. |
76 | + * TODO: This just swallows errors! | |
76 | 77 | */ |
77 | 78 | #define CIN_MIXER_SOUND_FROM_SOFT_LOADER(LD, FMT, OUT, ALLOCATOR) do{ \ |
78 | 79 | const struct Cin_Loader *const CIN_MIXER_loader = (LD);\ |
@@ -95,6 +96,7 @@ CIN_PRIVATE(void) Cin_ResampleSound(const struct Cin_Loader *from, | ||
95 | 96 | struct Cin_MixerSound *const CIN_MIXER_out = \ |
96 | 97 | ALLOCATOR(sizeof(struct Cin_MixerSound) + CIN_MIXER_out_size); \ |
97 | 98 | (OUT) = CIN_MIXER_out; \ |
99 | + CIN_MIXER_out->byte_len = CIN_MIXER_out_size; \ | |
98 | 100 | for(CIN_MIXER_loader_data = CIN_MIXER_loader->first; \ |
99 | 101 | CIN_MIXER_loader_data != NULL; \ |
100 | 102 | CIN_MIXER_loader_data = CIN_MIXER_loader_data->next){ \ |
@@ -105,6 +107,7 @@ CIN_PRIVATE(void) Cin_ResampleSound(const struct Cin_Loader *from, | ||
105 | 107 | CIN_SOFT_LOADER_DATA(CIN_MIXER_loader_data), \ |
106 | 108 | CIN_MIXER_out_format, \ |
107 | 109 | CIN_MIXER_SOUND_PCM(CIN_MIXER_out) + CIN_MIXER_i); \ |
110 | + if(CIN_MIXER_added == 0) break; \ | |
108 | 111 | CIN_MIXER_i += CIN_MIXER_added; \ |
109 | 112 | } \ |
110 | 113 | } \ |
@@ -22,5 +22,5 @@ libcin_mixer.a: $(MIXER_OBJECTS) | ||
22 | 22 | cin_mixer_sound.o: cin_mixer_sound.c cin_mixer_sound.h cin_dsp.h $(ROOTDIR)/cin_export.h $(ROOTDIR)/cin_format.h |
23 | 23 | $(CC) $(CFLAGS) -I"$(ROOTDIR)" -c cin_mixer_sound.c -o cin_mixer_sound.o |
24 | 24 | |
25 | -cin_dsp.o: cin_dsp.c cin_dsp.h | |
25 | +cin_dsp.o: cin_dsp.c cin_dsp.h cin_convert_core.inc | |
26 | 26 | $(CC) $(CFLAGS) -c cin_dsp.c -o cin_dsp.o |
@@ -20,6 +20,7 @@ | ||
20 | 20 | |
21 | 21 | #include <assert.h> |
22 | 22 | #include <stdlib.h> |
23 | +#include <stdio.h> | |
23 | 24 | #include <string.h> |
24 | 25 | #include <unistd.h> |
25 | 26 | #include <time.h> |
@@ -40,6 +41,8 @@ void *Cin_OSS_ThreadFunc(void *v){ | ||
40 | 41 | const int bytes_per_frame = CIN_FORMAT_BYTES_PER_SAMPLE(format) * num_channels; |
41 | 42 | const int buffer_size = (bytes_per_frame * rate) / 10; |
42 | 43 | |
44 | + const void *input_data[CIN_OSS_SOUND_CHANNELS+1]; | |
45 | + | |
43 | 46 | void *const buffer = malloc(buffer_size); |
44 | 47 | |
45 | 48 | CIN_DSP_NEW_STACK_FMT_STRUCT(dsp_fmt); |
@@ -73,11 +76,75 @@ iter: | ||
73 | 76 | } |
74 | 77 | |
75 | 78 | if(active_channels != 0){ |
76 | - Cin_DSP_Mix(buffer_size, dsp_fmt, active_channels, channels, buffer); | |
79 | + /* First, mix any finalizing channels (channels without enough data to | |
80 | + * fill the buffer) | |
81 | + */ | |
77 | 82 | i = 0; |
83 | + | |
84 | + /* Find the first channel which is being finalized, if any. */ | |
78 | 85 | do{ |
79 | - channels[i]->position += buffer_size; | |
86 | + if(channels[i]->position + buffer_size > | |
87 | + channels[i]->byte_len){ | |
88 | + break; | |
89 | + } | |
80 | 90 | }while(++i < active_channels); |
91 | + | |
92 | + /* Check this only if we broke early (found a finalizing channel) */ | |
93 | + if(i != active_channels){ | |
94 | + input_data[0] = buffer; | |
95 | + | |
96 | + /* Very fortunately, zero-init is ALSO zero in float and double */ | |
97 | + memset(buffer, 0, buffer_size); | |
98 | + | |
99 | + do{ | |
100 | + struct Cin_MixerSound *const snd = channels[i]; | |
101 | + const int remaining_length = | |
102 | + snd->byte_len - snd->position; | |
103 | + if(remaining_length < buffer_size){ | |
104 | + input_data[1] = CIN_MIXER_SOUND_PCM(channels[i]) + | |
105 | + snd->position; | |
106 | + | |
107 | + Cin_DSP_Mix(remaining_length, | |
108 | + dsp_fmt, | |
109 | + 2, | |
110 | + input_data, | |
111 | + buffer); | |
112 | + | |
113 | + /* Pull out this channel by simply swapping in the final | |
114 | + * element. This makes removing any element constant time, | |
115 | + * and is acceptable because the order of the channels is | |
116 | + * not important. | |
117 | + */ | |
118 | + channels[i] = channels[--active_channels]; | |
119 | + } | |
120 | + else{ | |
121 | + i++; | |
122 | + } | |
123 | + }while(i < active_channels); | |
124 | + | |
125 | + /* Set i = 1, so that we do not place anything over the input_data | |
126 | + * element containing our mixed finalizing sounds. | |
127 | + */ | |
128 | + i = 1; | |
129 | + } | |
130 | + else{ | |
131 | + /* No finalizing sounds, so no extra inputs. */ | |
132 | + i = 0; | |
133 | + } | |
134 | + | |
135 | + /* No need to remix if all channels were finalizing. */ | |
136 | + if(active_channels != 0){ | |
137 | + register unsigned source_i = 0; | |
138 | + do{ | |
139 | + input_data[i++] = CIN_MIXER_SOUND_PCM(channels[source_i]) + | |
140 | + channels[source_i]->position; | |
141 | + channels[source_i]->position += buffer_size; | |
142 | + }while(++source_i < active_channels); | |
143 | + } | |
144 | + /* i contains the final element placed into input_data, regardless | |
145 | + * of how many were from the input channels. | |
146 | + */ | |
147 | + Cin_DSP_Mix(buffer_size, dsp_fmt, i, input_data, buffer); | |
81 | 148 | } |
82 | 149 | else{ |
83 | 150 | memset(buffer, 0, buffer_size); |
@@ -7,6 +7,7 @@ | ||
7 | 7 | |
8 | 8 | #include "cin_oss_driver.h" |
9 | 9 | #include "cin_oss_sound.h" |
10 | +#include "cin_mixer_sound.h" | |
10 | 11 | #include "cin_oss.h" |
11 | 12 | #include "cinnamon.h" |
12 | 13 |
@@ -119,7 +120,7 @@ CIN_PRIVATE(int) Cin_OSS_NewID(struct Cin_Driver *drv){ | ||
119 | 120 | CIN_PRIVATE(int) Cin_OSS_PushCommand(struct Cin_Driver *drv, |
120 | 121 | struct Cin_OSS_Command *cmd){ |
121 | 122 | TAILQ_INSERT_TAIL(&drv->commands, cmd, entries); |
122 | - return 1; | |
123 | + return 0; | |
123 | 124 | } |
124 | 125 | |
125 | 126 | /*****************************************************************************/ |
@@ -203,21 +204,30 @@ CIN_PRIVATE(int) Cin_OSS_ProcessCommands(struct Cin_Driver *drv){ | ||
203 | 204 | |
204 | 205 | switch(command){ |
205 | 206 | case CIN_OSS_INSERT: |
206 | - puts("CIN_OSS_INSERT"); | |
207 | + /* puts("CIN_OSS_INSERT"); */ | |
207 | 208 | SLIST_INSERT_HEAD(&drv->sounds, sound, entries); |
208 | 209 | break; |
209 | 210 | case CIN_OSS_DELETE: |
210 | - puts("CIN_OSS_DELETE"); | |
211 | + /* puts("CIN_OSS_DELETE"); */ | |
211 | 212 | if(prev == NULL) |
212 | 213 | SLIST_REMOVE_HEAD(&drv->sounds, entries); |
213 | 214 | else |
215 | + /* When compiling on Linux with OSS emulation, we need to | |
216 | + * deal with not having this macro. */ | |
217 | +#ifndef SLIST_REMOVE_AFTER | |
218 | + SLIST_REMOVE(&drv->sounds, | |
219 | + SLIST_NEXT(prev, entries), | |
220 | + Cin_OSS_Sound, | |
221 | + entries); | |
222 | +#else | |
214 | 223 | SLIST_REMOVE_AFTER(prev, entries); |
224 | +#endif | |
215 | 225 | /* We want to stop any playing instances of this sound. */ |
216 | 226 | |
217 | 227 | /* FALLTHROUGH */ |
218 | 228 | case CIN_OSS_STOP: |
219 | - if(command == CIN_OSS_STOP) | |
220 | - puts("CIN_OSS_STOP"); | |
229 | + /* if(command == CIN_OSS_STOP) | |
230 | + puts("CIN_OSS_STOP"); */ | |
221 | 231 | for(i = 0; i < CIN_OSS_SOUND_CHANNELS; i++){ |
222 | 232 | if(drv->channels[i] == sound->snd){ |
223 | 233 | drv->channels[i] = NULL; |
@@ -225,10 +235,25 @@ CIN_PRIVATE(int) Cin_OSS_ProcessCommands(struct Cin_Driver *drv){ | ||
225 | 235 | } |
226 | 236 | break; |
227 | 237 | case CIN_OSS_PLAY: |
228 | - puts("CIN_OSS_PLAY"); | |
238 | + /* puts("CIN_OSS_PLAY"); */ | |
239 | + | |
240 | + /* Check if the sound is already playing, and do nothing | |
241 | + * if it is. | |
242 | + */ | |
243 | + for(i = 0; i < CIN_OSS_SOUND_CHANNELS; i++){ | |
244 | + if(drv->channels[i] == sound->snd){ | |
245 | + sound = NULL; | |
246 | + /* Found. */ | |
247 | + break; | |
248 | + } | |
249 | + } | |
250 | + if(sound == NULL) | |
251 | + break; | |
252 | + | |
229 | 253 | for(i = 0; i < CIN_OSS_SOUND_CHANNELS; i++){ |
230 | 254 | if(drv->channels[i] == NULL){ |
231 | 255 | drv->channels[i] = sound->snd; |
256 | + drv->channels[i]->position = 0; | |
232 | 257 | break; |
233 | 258 | } |
234 | 259 | } |
@@ -239,7 +264,7 @@ CIN_PRIVATE(int) Cin_OSS_ProcessCommands(struct Cin_Driver *drv){ | ||
239 | 264 | */ |
240 | 265 | break; |
241 | 266 | case CIN_OSS_QUIT: |
242 | - puts("CIN_OSS_QUIT"); | |
267 | + /* puts("CIN_OSS_QUIT"); */ | |
243 | 268 | /* Keep going so that we at least drain the queue. */ |
244 | 269 | val = 1; |
245 | 270 | break; |
@@ -366,12 +391,12 @@ enum Cin_DriverError Cin_CreateDriver(struct Cin_Driver *drv){ | ||
366 | 391 | |
367 | 392 | drv->rate = val; |
368 | 393 | |
369 | - /* Set the buffer size. */ | |
394 | + /* Set the buffer size. | |
370 | 395 | val = 0x0004000B; |
371 | 396 | if(ioctl(dev, SNDCTL_DSP_SETFRAGMENT, &val) == -1){ |
372 | 397 | ret = Cin_eDriverFailure; |
373 | 398 | goto fail_device; |
374 | - } | |
399 | + } */ | |
375 | 400 | } |
376 | 401 | |
377 | 402 | { |
@@ -401,7 +426,7 @@ void Cin_DestroyDriver(struct Cin_Driver *drv){ | ||
401 | 426 | Cin_OSS_PushCommand(drv, quit); |
402 | 427 | { |
403 | 428 | void *unused; |
404 | - pthread_join(&drv->thread, &unused); | |
429 | + pthread_join(drv->thread, &unused); | |
405 | 430 | } |
406 | 431 | /* Finalize the driver. */ |
407 | 432 | close(drv->dev); |
@@ -26,16 +26,22 @@ static enum Cin_SoundError cin_sound_command(struct Cin_Sound *snd, int type){ | ||
26 | 26 | struct Cin_OSS_Command *cmd = Cin_OSS_NewCommand(snd->sound_id, type); |
27 | 27 | |
28 | 28 | if(Cin_OSS_Lock(snd->drv) != 0){ |
29 | + assert(!"Could not lock"); | |
29 | 30 | return Cin_eSoundFailure; |
30 | 31 | } |
31 | 32 | |
32 | - if(Cin_OSS_PushCommand(snd->drv, cmd) != 0) | |
33 | + if(Cin_OSS_PushCommand(snd->drv, cmd) != 0){ | |
34 | + assert(!"Could not push command"); | |
33 | 35 | ret = Cin_eSoundFailure; |
34 | - | |
35 | - if(Cin_OSS_Unlock(snd->drv) != 0) | |
36 | + } | |
37 | + | |
38 | + if(Cin_OSS_Unlock(snd->drv) != 0){ | |
39 | + assert(!"Could not unlock"); | |
36 | 40 | return Cin_eSoundFailure; |
37 | - else | |
41 | + } | |
42 | + else{ | |
38 | 43 | return ret; |
44 | + } | |
39 | 45 | } |
40 | 46 | |
41 | 47 | /*****************************************************************************/ |
@@ -9,14 +9,14 @@ CIN_COMMONLIB=$(ROOTDIR)/common/libcin_common.a | ||
9 | 9 | CIN_MIXERLIB=$(ROOTDIR)/common/libcin_mixer.a |
10 | 10 | |
11 | 11 | libcin_oss_x.a: $(OBJECTS) |
12 | - if [[ -f libcin_oss_x2.a ]] ; then rm libcin_oss_x2.a ; fi | |
12 | + if [ -f libcin_oss_x2.a ] ; then rm libcin_oss_x2.a ; fi | |
13 | 13 | $(AR) rc libcin_oss_x2.a $(OBJECTS) |
14 | 14 | $(RANLIB) libcin_oss_x2.a |
15 | 15 | mv libcin_oss_x2.a libcin_oss_x.a |
16 | 16 | |
17 | 17 | libcin_oss.a: $(CIN_COMMONLIB) $(CIN_MIXERLIB) libcin_oss_x.a |
18 | - if [[ -f libcin_oss2.a ]] ; then rm libcin_oss2.a ; fi | |
19 | - echo $$'create libcin_oss2.a\naddlib libcin_oss_x.a\naddlib $(CIN_COMMONLIB)\naddlib $(CIN_MIXERLIB)\nsave\nend\n' | $(AR) M | |
18 | + if [ -f libcin_oss2.a ] ; then rm libcin_oss2.a ; fi | |
19 | + echo 'create libcin_oss2.a\naddlib libcin_oss_x.a\naddlib $(CIN_COMMONLIB)\naddlib $(CIN_MIXERLIB)\nsave\nend\n' | $(AR) M | |
20 | 20 | $(RANLIB) libcin_oss2.a |
21 | 21 | mv libcin_oss2.a libcin_oss.a |
22 | 22 |
@@ -26,7 +26,7 @@ cin_oss.o: cin_oss.c cin_oss.h cin_oss_driver.h cin_oss_sound.h $(COMMONHEADERS) | ||
26 | 26 | $(CC) $(CFLAGS) -I"$(ROOTDIR)" -I"$(ROOTDIR)/common" -c cin_oss.c -o cin_oss.o |
27 | 27 | |
28 | 28 | cin_oss_driver.o: cin_oss_driver.c cin_oss_driver.h cin_oss.h $(COMMONHEADERS) |
29 | - $(CC) $(CFLAGS) -I"$(ROOTDIR)" -c cin_oss_driver.c -o cin_oss_driver.o | |
29 | + $(CC) $(CFLAGS) -I"$(ROOTDIR)" -I"$(ROOTDIR)/common" -c cin_oss_driver.c -o cin_oss_driver.o | |
30 | 30 | |
31 | 31 | cin_oss_sound.o: cin_oss_sound.c cin_oss.h $(COMMONHEADERS) ../common/cin_soft_loader.h ../common/cin_mixer_sound.h |
32 | 32 | $(CC) $(CFLAGS) -I"$(ROOTDIR)" -I"$(ROOTDIR)/common" -c cin_oss_sound.c -o cin_oss_sound.o |