1 /**
2 * Stream a sound to SDL_mixer by abusing Mix_RegisterEffect
3
4 * Copyright (C) 2007 Sylvain Beucler
5
6 * This file is part of GNU FreeDink
7
8 * GNU FreeDink is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 3 of the
11 * License, or (at your option) any later version.
12
13 * GNU FreeDink is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see
20 * <http://www.gnu.org/licenses/>.
21 */
22
23 #include "SDL.h"
24 #include "SDL_mixer.h"
25 #include <math.h>
26 #include <stdbool.h>
27
28 int global_halt = 0;
29
30 /**
31 * Display a SDL audio-format in human-readable form
32 **/
format2string(Uint16 format)33 static const char *format2string(Uint16 format) {
34 char *format_str = "Unknown";
35 switch (format)
36 {
37 case AUDIO_U8: format_str = "U8"; break;
38 case AUDIO_S8: format_str = "S8"; break;
39 case AUDIO_U16LSB: format_str = "U16LSB"; break;
40 case AUDIO_S16LSB: format_str = "S16LSB"; break;
41 case AUDIO_U16MSB: format_str = "U16MSB"; break;
42 case AUDIO_S16MSB: format_str = "S16MSB"; break;
43 }
44 return format_str;
45 }
46
47
48 /**
49 * Hold the state of the 'effect'
50 */
51 struct sine_state
52 {
53 int x;
54 int loop;
55 };
56
57 /**
58 * Generate a A-440Hz sine, starting at x coordinate 'udata->x' and lasting
59 * 'len'/2 frames
60 */
gen_sine(int chan,void * stream,int len,void * udata)61 void gen_sine(int chan, void *stream, int len, void *udata)
62 {
63 printf("gen_sine(%d)\n", len);
64 struct sine_state* data = (struct sine_state*)udata;
65 Sint16* pstream = (Sint16*) stream;
66
67 int max_vol = 1<<(2*8-1) - 1; // 127
68 int vol = max_vol * .75;
69
70 for (int i = 0; i < len/2/2; i++)
71 {
72 /* Fill 'stream' */
73 Sint16 y = sin(data->x*6.28*440/44100) * vol;
74 *pstream = y;
75 pstream++;
76 *pstream = y; /* stereo */
77 pstream++;
78 data->x++;
79 }
80
81 data->loop++;
82 if (data->loop == 10)
83 {
84 //Mix_HaltChannel(1);
85 global_halt = 1;
86 }
87 }
gen_sine_cleanup(int chan,void * udata)88 void gen_sine_cleanup(int chan, void *udata)
89 {
90 free(udata);
91 }
92
93 /**
94 * Free channel resources if any
95 */
channel_cleanup(int channel)96 void channel_cleanup(int channel)
97 {
98 }
99
100 /**
101 * Work-around a streamed chunk support in SDL_mixer, by running an
102 * effect over a small chunk ran in loop
103 */
main(void)104 int main(void)
105 {
106 /* Init */
107 SDL_Init(SDL_INIT_AUDIO);
108 Mix_OpenAudio(44100, AUDIO_S16LSB,
109 MIX_DEFAULT_CHANNELS, 4096 /* 4096 */);
110 Mix_AllocateChannels(1);
111
112 /* Dump audio info */
113 {
114 int hw_freq, hw_channels;
115 Uint16 hw_format;
116 int numtimesopened;
117 numtimesopened = Mix_QuerySpec(&hw_freq, &hw_format, &hw_channels);
118 if (!numtimesopened)
119 printf("Mix_QuerySpec: %s\n", Mix_GetError());
120 else
121 printf("Audio hardware info: frequency=%dHz\tformat=%s\tchannels=%d\topened=%d times\n",
122 hw_freq, format2string(hw_format), hw_channels, numtimesopened);
123 }
124
125 char buf[409600];
126 Mix_Chunk *chunk = Mix_QuickLoad_RAW(buf, 409600);
127 if (chunk == NULL)
128 printf("Mix_QuickLoad_RAW: %s\n", Mix_GetError());
129
130
131 /** Play a A-440hz pure sound **/
132 Mix_Pause(0);
133 int channel = Mix_PlayChannel(0, chunk, -1);
134 printf("Using channel %d\n", channel);/* error */
135 if (channel < 0)
136 printf("Error %d\n", channel);/* error */
137
138 /* Register sound generator */
139 struct sine_state *data = calloc(1, sizeof(struct sine_state));
140 data->x = 0;
141 Mix_RegisterEffect(channel, gen_sine, gen_sine_cleanup, data);
142 Mix_ChannelFinished(channel_cleanup);
143
144 Mix_Resume(channel);
145
146 /* Play chunk with looping (infinite play) */
147 while (global_halt == 0)
148 {
149 SDL_Delay(100);
150 }
151 }
152
153
154 /**
155 * Local Variables:
156 * compile-command: "gcc test.c -std=c99 `sdl-config --cflags --libs` -lSDL_mixer"
157 * End:
158 */
159