Mercurial > audlegacy
annotate Plugins/Input/tonegen/tonegen.c @ 414:7fa1738514d5 trunk
[svn] Convert all input plugins (except timidity & wav-sndfile) to produce_audio.
author | chainsaw |
---|---|
date | Tue, 10 Jan 2006 12:22:40 -0800 |
parents | bd8457b077cf |
children | d539e5c5f730 |
rev | line source |
---|---|
61 | 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
18 */ | |
19 | |
20 #include "audacious/plugin.h" | |
414
7fa1738514d5
[svn] Convert all input plugins (except timidity & wav-sndfile) to produce_audio.
chainsaw
parents:
209
diff
changeset
|
21 #include "audacious/output.h" |
61 | 22 #include "libaudacious/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; | |
172 | 43 static GThread *play_thread; |
61 | 44 |
45 static void tone_about(void) | |
46 { | |
47 static GtkWidget *box; | |
48 box = xmms_show_message( | |
49 _("About Tone Generator"), | |
50 /* I18N: UTF-8 Translation: "Haavard Kvaalen" -> "H\303\245vard Kv\303\245len" */ | |
51 _("Sinus tone generator by Haavard Kvaalen <havardk@xmms.org>\n" | |
52 "Modified by Daniel J. Peng <danielpeng@bigfoot.com>\n\n" | |
53 "To use it, add a URL: tone://frequency1;frequency2;frequency3;...\n" | |
54 "e.g. tone://2000;2005 to play a 2000Hz tone and a 2005Hz tone"), | |
55 _("Ok"), FALSE, NULL, NULL); | |
209
bd8457b077cf
[svn] Add casts to callbacks in signal handlers to avoid warning. Remove stale pause handler declaration from wav-sndfile.h
chainsaw
parents:
190
diff
changeset
|
56 g_signal_connect(GTK_OBJECT(box), "destroy", |
bd8457b077cf
[svn] Add casts to callbacks in signal handlers to avoid warning. Remove stale pause handler declaration from wav-sndfile.h
chainsaw
parents:
190
diff
changeset
|
57 (GCallback)gtk_widget_destroyed, &box); |
61 | 58 } |
59 | |
60 static int tone_is_our_file(char *filename) | |
61 { | |
62 if (!strncmp(filename, "tone://", 7)) | |
63 return TRUE; | |
64 return FALSE; | |
65 } | |
66 | |
67 #define BUF_SAMPLES 512 | |
68 #define BUF_BYTES BUF_SAMPLES * 2 | |
69 | |
70 static void* play_loop(void *arg) | |
71 { | |
72 GArray* frequencies = arg; | |
73 gint16 data[BUF_SAMPLES]; | |
74 int i; | |
75 struct { | |
76 double wd; | |
77 unsigned int period, t; | |
78 } *tone; | |
79 | |
80 tone = g_malloc(frequencies->len * sizeof(*tone)); | |
81 | |
82 for (i = 0; i < frequencies->len; i++) | |
83 { | |
84 double f = g_array_index(frequencies, double, i); | |
85 tone[i].wd = 2 * PI * f / OUTPUT_FREQ; | |
86 tone[i].period = (G_MAXINT * 2U / OUTPUT_FREQ) * | |
87 (OUTPUT_FREQ / f); | |
88 tone[i].t = 0; | |
89 } | |
90 | |
91 while (going) | |
92 { | |
93 for (i = 0; i < BUF_SAMPLES; i++) | |
94 { | |
95 int j; | |
96 double sum_sines; | |
97 | |
98 for (sum_sines = 0, j = 0; j < frequencies->len; j++) | |
99 { | |
100 sum_sines += sin(tone[j].wd * tone[j].t); | |
101 if (tone[j].t > tone[j].period) | |
102 tone[j].t -= tone[j].period; | |
103 tone[j].t++; | |
104 } | |
105 data[i] = rint(((1 << 15) - 1) * | |
106 (sum_sines / frequencies->len)); | |
107 } | |
108 while (tone_ip.output->buffer_free() < BUF_BYTES && going) | |
109 xmms_usleep(30000); | |
414
7fa1738514d5
[svn] Convert all input plugins (except timidity & wav-sndfile) to produce_audio.
chainsaw
parents:
209
diff
changeset
|
110 produce_audio(tone_ip.output->written_time(), FMT_S16_NE, 1, BUF_BYTES, data, &going); |
61 | 111 } |
112 | |
113 g_array_free(frequencies, TRUE); | |
114 g_free(tone); | |
115 | |
116 /* Make sure the output plugin stops prebuffering */ | |
117 tone_ip.output->buffer_free(); | |
118 tone_ip.output->buffer_free(); | |
119 | |
172 | 120 g_thread_exit(NULL); |
190 | 121 return(NULL); |
61 | 122 } |
123 | |
124 static GArray* tone_filename_parse(const char* filename) | |
125 { | |
126 GArray *frequencies = g_array_new(FALSE, FALSE, sizeof(double)); | |
127 char **strings, **ptr; | |
128 | |
129 if (strncmp(filename,"tone://", 7)) | |
130 return NULL; | |
131 | |
132 filename += 7; | |
133 strings = g_strsplit(filename, ";", 100); | |
134 | |
135 for (ptr = strings; *ptr != NULL; ptr++) | |
136 { | |
137 double freq = strtod(*ptr, NULL); | |
138 if (freq >= MIN_FREQ && freq <= MAX_FREQ) | |
139 g_array_append_val(frequencies, freq); | |
140 } | |
141 g_strfreev(strings); | |
142 | |
143 if (frequencies->len == 0) | |
144 { | |
145 g_array_free(frequencies, TRUE); | |
146 frequencies = NULL; | |
147 } | |
148 | |
149 return frequencies; | |
150 } | |
151 | |
152 static char* tone_title(char *filename) | |
153 { | |
154 GArray *freqs; | |
155 char* title; | |
156 int i; | |
157 | |
158 freqs = tone_filename_parse(filename); | |
159 if (freqs == NULL) | |
160 return NULL; | |
161 | |
162 title = g_strdup_printf("%s %.1f Hz", _("Tone Generator: "), | |
163 g_array_index(freqs, double, 0)); | |
164 for (i = 1; i < freqs->len; i++) | |
165 { | |
166 char *old_title; | |
167 old_title = title; | |
168 title = g_strdup_printf("%s;%.1f Hz", old_title, | |
169 g_array_index(freqs, double, i)); | |
170 g_free(old_title); | |
171 } | |
172 g_array_free(freqs, TRUE); | |
173 | |
174 return title; | |
175 } | |
176 | |
177 | |
178 static void tone_play(char *filename) | |
179 { | |
180 GArray* frequencies; | |
181 char *name; | |
182 | |
183 frequencies = tone_filename_parse(filename); | |
184 if (frequencies == NULL) | |
185 return; | |
186 | |
187 going = TRUE; | |
188 audio_error = FALSE; | |
189 if (tone_ip.output->open_audio(FMT_S16_NE, OUTPUT_FREQ, 1) == 0) | |
190 { | |
191 audio_error = TRUE; | |
192 going = FALSE; | |
193 return; | |
194 } | |
195 | |
196 name = tone_title(filename); | |
197 tone_ip.set_info(name, -1, 16 * OUTPUT_FREQ, OUTPUT_FREQ, 1); | |
198 g_free(name); | |
172 | 199 play_thread = g_thread_create((GThreadFunc)play_loop, frequencies, TRUE, NULL); |
61 | 200 } |
201 | |
202 static void tone_stop(void) | |
203 { | |
204 if (going) | |
205 { | |
206 going = FALSE; | |
172 | 207 g_thread_join(play_thread); |
61 | 208 tone_ip.output->close_audio(); |
209 } | |
210 } | |
211 | |
212 static void tone_pause(short paused) | |
213 { | |
214 tone_ip.output->pause(paused); | |
215 } | |
216 | |
217 static int tone_get_time(void) | |
218 { | |
219 if (audio_error) | |
220 return -2; | |
221 if (!going && !tone_ip.output->buffer_playing()) | |
222 return -1; | |
223 return tone_ip.output->output_time(); | |
224 } | |
225 | |
226 static void tone_song_info(char *filename, char **title, int *length) | |
227 { | |
228 *length = -1; | |
229 *title = tone_title(filename); | |
230 } | |
231 | |
232 static InputPlugin tone_ip = | |
233 { | |
234 NULL, | |
235 NULL, | |
236 NULL, /* Description */ | |
237 NULL, | |
238 tone_about, | |
239 NULL, | |
240 tone_is_our_file, | |
241 NULL, | |
242 tone_play, | |
243 tone_stop, | |
244 tone_pause, | |
245 NULL, | |
246 NULL, | |
247 tone_get_time, | |
248 NULL, | |
249 NULL, | |
250 NULL, | |
251 NULL, | |
252 NULL, | |
253 NULL, | |
254 NULL, | |
255 tone_song_info, | |
256 NULL, | |
257 NULL | |
258 }; | |
259 | |
260 InputPlugin *get_iplugin_info(void) | |
261 { | |
262 tone_ip.description = g_strdup_printf(_("Tone Generator %s"), VERSION); | |
263 return &tone_ip; | |
264 } |