Mercurial > audlegacy-plugins
comparison src/tonegen/tonegen.c @ 12:3da1b8942b8b trunk
[svn] - remove src/Input src/Output src/Effect src/General src/Visualization src/Container
author | nenolod |
---|---|
date | Mon, 18 Sep 2006 03:14:20 -0700 |
parents | src/Input/tonegen/tonegen.c@088092a52fea |
children | d124034ebea3 |
comparison
equal
deleted
inserted
replaced
11:cff1d04026ae | 12:3da1b8942b8b |
---|---|
1 /* | |
2 * Copyright 2000,2001 Haavard Kvaalen <havardk@sol.no> | |
3 * | |
4 * | |
5 * This program is free software; you can redistribute it and/or modify | |
6 * it under the terms of the GNU General Public License as published by | |
7 * the Free Software Foundation; either version 2 of the License, or | |
8 * (at your option) any later version. | |
9 * | |
10 * This program is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 * GNU General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU General Public License | |
16 * along with this program; if not, write to the Free Software | |
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
18 */ | |
19 | |
20 #include "audacious/plugin.h" | |
21 #include "audacious/output.h" | |
22 #include "audacious/util.h" | |
23 #include "config.h" | |
24 #include <glib.h> | |
25 #include <stdlib.h> | |
26 #include <string.h> | |
27 #include <math.h> | |
28 #include <stdio.h> | |
29 #include <glib/gi18n.h> | |
30 | |
31 #define MIN_FREQ 10 | |
32 #define MAX_FREQ 20000 | |
33 #define OUTPUT_FREQ 44100 | |
34 | |
35 #ifndef PI | |
36 #define PI 3.14159265358979323846 | |
37 #endif | |
38 | |
39 static InputPlugin tone_ip; | |
40 | |
41 static gboolean going; | |
42 static gboolean audio_error; | |
43 static GThread *play_thread; | |
44 | |
45 static void tone_about(void) | |
46 { | |
47 static GtkWidget *box; | |
48 if (!box) | |
49 { | |
50 box = xmms_show_message( | |
51 _("About Tone Generator"), | |
52 /* I18N: UTF-8 Translation: "Haavard Kvaalen" -> "H\303\245vard Kv\303\245len" */ | |
53 _("Sinus tone generator by Haavard Kvaalen <havardk@xmms.org>\n" | |
54 "Modified by Daniel J. Peng <danielpeng@bigfoot.com>\n\n" | |
55 "To use it, add a URL: tone://frequency1;frequency2;frequency3;...\n" | |
56 "e.g. tone://2000;2005 to play a 2000Hz tone and a 2005Hz tone"), | |
57 _("Ok"), FALSE, NULL, NULL); | |
58 g_signal_connect(GTK_OBJECT(box), "destroy", | |
59 (GCallback)gtk_widget_destroyed, &box); | |
60 } | |
61 } | |
62 | |
63 static int tone_is_our_file(char *filename) | |
64 { | |
65 if (!strncmp(filename, "tone://", 7)) | |
66 return TRUE; | |
67 return FALSE; | |
68 } | |
69 | |
70 #define BUF_SAMPLES 512 | |
71 #define BUF_BYTES BUF_SAMPLES * 2 | |
72 | |
73 static void* play_loop(void *arg) | |
74 { | |
75 GArray* frequencies = arg; | |
76 gint16 data[BUF_SAMPLES]; | |
77 gsize i; | |
78 struct { | |
79 double wd; | |
80 unsigned int period, t; | |
81 } *tone; | |
82 | |
83 tone = g_malloc(frequencies->len * sizeof(*tone)); | |
84 | |
85 for (i = 0; i < frequencies->len; i++) | |
86 { | |
87 double f = g_array_index(frequencies, double, i); | |
88 tone[i].wd = 2 * PI * f / OUTPUT_FREQ; | |
89 tone[i].period = (G_MAXINT * 2U / OUTPUT_FREQ) * | |
90 (OUTPUT_FREQ / f); | |
91 tone[i].t = 0; | |
92 } | |
93 | |
94 while (going) | |
95 { | |
96 for (i = 0; i < BUF_SAMPLES; i++) | |
97 { | |
98 gsize j; | |
99 double sum_sines; | |
100 | |
101 for (sum_sines = 0, j = 0; j < frequencies->len; j++) | |
102 { | |
103 sum_sines += sin(tone[j].wd * tone[j].t); | |
104 if (tone[j].t > tone[j].period) | |
105 tone[j].t -= tone[j].period; | |
106 tone[j].t++; | |
107 } | |
108 data[i] = rint(((1 << 15) - 1) * | |
109 (sum_sines / frequencies->len)); | |
110 } | |
111 while (tone_ip.output->buffer_free() < BUF_BYTES && going) | |
112 xmms_usleep(30000); | |
113 produce_audio(tone_ip.output->written_time(), FMT_S16_NE, 1, BUF_BYTES, data, &going); | |
114 } | |
115 | |
116 g_array_free(frequencies, TRUE); | |
117 g_free(tone); | |
118 | |
119 /* Make sure the output plugin stops prebuffering */ | |
120 tone_ip.output->buffer_free(); | |
121 tone_ip.output->buffer_free(); | |
122 | |
123 g_thread_exit(NULL); | |
124 return(NULL); | |
125 } | |
126 | |
127 static GArray* tone_filename_parse(const char* filename) | |
128 { | |
129 GArray *frequencies = g_array_new(FALSE, FALSE, sizeof(double)); | |
130 char **strings, **ptr; | |
131 | |
132 if (strncmp(filename,"tone://", 7)) | |
133 return NULL; | |
134 | |
135 filename += 7; | |
136 strings = g_strsplit(filename, ";", 100); | |
137 | |
138 for (ptr = strings; *ptr != NULL; ptr++) | |
139 { | |
140 double freq = strtod(*ptr, NULL); | |
141 if (freq >= MIN_FREQ && freq <= MAX_FREQ) | |
142 g_array_append_val(frequencies, freq); | |
143 } | |
144 g_strfreev(strings); | |
145 | |
146 if (frequencies->len == 0) | |
147 { | |
148 g_array_free(frequencies, TRUE); | |
149 frequencies = NULL; | |
150 } | |
151 | |
152 return frequencies; | |
153 } | |
154 | |
155 static char* tone_title(char *filename) | |
156 { | |
157 GArray *freqs; | |
158 char* title; | |
159 gsize i; | |
160 | |
161 freqs = tone_filename_parse(filename); | |
162 if (freqs == NULL) | |
163 return NULL; | |
164 | |
165 title = g_strdup_printf("%s %.1f Hz", _("Tone Generator: "), | |
166 g_array_index(freqs, double, 0)); | |
167 for (i = 1; i < freqs->len; i++) | |
168 { | |
169 char *old_title; | |
170 old_title = title; | |
171 title = g_strdup_printf("%s;%.1f Hz", old_title, | |
172 g_array_index(freqs, double, i)); | |
173 g_free(old_title); | |
174 } | |
175 g_array_free(freqs, TRUE); | |
176 | |
177 return title; | |
178 } | |
179 | |
180 | |
181 static void tone_play(char *filename) | |
182 { | |
183 GArray* frequencies; | |
184 char *name; | |
185 | |
186 frequencies = tone_filename_parse(filename); | |
187 if (frequencies == NULL) | |
188 return; | |
189 | |
190 going = TRUE; | |
191 audio_error = FALSE; | |
192 if (tone_ip.output->open_audio(FMT_S16_NE, OUTPUT_FREQ, 1) == 0) | |
193 { | |
194 audio_error = TRUE; | |
195 going = FALSE; | |
196 return; | |
197 } | |
198 | |
199 name = tone_title(filename); | |
200 tone_ip.set_info(name, -1, 16 * OUTPUT_FREQ, OUTPUT_FREQ, 1); | |
201 g_free(name); | |
202 play_thread = g_thread_create((GThreadFunc)play_loop, frequencies, TRUE, NULL); | |
203 } | |
204 | |
205 static void tone_stop(void) | |
206 { | |
207 if (going) | |
208 { | |
209 going = FALSE; | |
210 g_thread_join(play_thread); | |
211 tone_ip.output->close_audio(); | |
212 } | |
213 } | |
214 | |
215 static void tone_pause(short paused) | |
216 { | |
217 tone_ip.output->pause(paused); | |
218 } | |
219 | |
220 static int tone_get_time(void) | |
221 { | |
222 if (audio_error) | |
223 return -2; | |
224 if (!going && !tone_ip.output->buffer_playing()) | |
225 return -1; | |
226 return tone_ip.output->output_time(); | |
227 } | |
228 | |
229 static void tone_song_info(char *filename, char **title, int *length) | |
230 { | |
231 *length = -1; | |
232 *title = tone_title(filename); | |
233 } | |
234 | |
235 static InputPlugin tone_ip = | |
236 { | |
237 NULL, | |
238 NULL, | |
239 NULL, /* Description */ | |
240 NULL, | |
241 tone_about, | |
242 NULL, | |
243 tone_is_our_file, | |
244 NULL, | |
245 tone_play, | |
246 tone_stop, | |
247 tone_pause, | |
248 NULL, | |
249 NULL, | |
250 tone_get_time, | |
251 NULL, | |
252 NULL, | |
253 NULL, | |
254 NULL, | |
255 NULL, | |
256 NULL, | |
257 NULL, | |
258 tone_song_info, | |
259 NULL, | |
260 NULL | |
261 }; | |
262 | |
263 InputPlugin *get_iplugin_info(void) | |
264 { | |
265 tone_ip.description = g_strdup_printf(_("Tone Generator %s"), PACKAGE_VERSION); | |
266 return &tone_ip; | |
267 } |