diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tonegen/tonegen.c	Mon Sep 18 03:14:20 2006 -0700
@@ -0,0 +1,267 @@
+/*
+ *  Copyright 2000,2001 Haavard Kvaalen <havardk@sol.no>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "audacious/plugin.h"
+#include "audacious/output.h"
+#include "audacious/util.h"
+#include "config.h"
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <stdio.h>
+#include <glib/gi18n.h>
+
+#define MIN_FREQ 10
+#define MAX_FREQ 20000
+#define OUTPUT_FREQ 44100
+
+#ifndef PI
+#define PI 3.14159265358979323846
+#endif
+
+static InputPlugin tone_ip;
+
+static gboolean going;
+static gboolean audio_error;
+static GThread *play_thread;
+
+static void tone_about(void)
+{
+	static GtkWidget *box;
+	if (!box)
+	{
+		box = xmms_show_message(
+			_("About Tone Generator"),
+	/* I18N: UTF-8 Translation: "Haavard Kvaalen" -> "H\303\245vard Kv\303\245len" */
+			_("Sinus tone generator by Haavard Kvaalen <havardk@xmms.org>\n"
+			  "Modified by Daniel J. Peng <danielpeng@bigfoot.com>\n\n"
+		  	"To use it, add a URL: tone://frequency1;frequency2;frequency3;...\n"
+		  	"e.g. tone://2000;2005 to play a 2000Hz tone and a 2005Hz tone"),
+			_("Ok"), FALSE, NULL, NULL);
+		g_signal_connect(GTK_OBJECT(box), "destroy",
+				   (GCallback)gtk_widget_destroyed, &box);
+	}
+}
+
+static int tone_is_our_file(char *filename)
+{
+	if (!strncmp(filename, "tone://", 7))
+		return TRUE;
+	return FALSE;
+}
+
+#define BUF_SAMPLES 512
+#define BUF_BYTES BUF_SAMPLES * 2
+
+static void* play_loop(void *arg)
+{
+	GArray* frequencies = arg;
+	gint16 data[BUF_SAMPLES];
+	gsize i;
+	struct {
+		double wd;
+		unsigned int period, t;
+	} *tone;
+
+	tone = g_malloc(frequencies->len * sizeof(*tone));
+
+	for (i = 0; i < frequencies->len; i++)
+	{
+		double f = g_array_index(frequencies, double, i);
+		tone[i].wd = 2 * PI * f / OUTPUT_FREQ;
+		tone[i].period = (G_MAXINT * 2U / OUTPUT_FREQ) *
+							(OUTPUT_FREQ / f);
+		tone[i].t = 0;
+	}
+
+	while (going)
+	{
+		for (i = 0; i < BUF_SAMPLES; i++)
+		{
+			gsize j;
+			double sum_sines;
+
+			for (sum_sines = 0, j = 0; j < frequencies->len; j++)
+			{
+				sum_sines += sin(tone[j].wd * tone[j].t);
+				if (tone[j].t > tone[j].period)
+					tone[j].t -= tone[j].period;
+				tone[j].t++;
+			}
+			data[i] = rint(((1 << 15) - 1) *
+				       (sum_sines / frequencies->len));
+		}
+		while (tone_ip.output->buffer_free() < BUF_BYTES && going)
+			xmms_usleep(30000);
+		produce_audio(tone_ip.output->written_time(), FMT_S16_NE, 1, BUF_BYTES, data, &going);
+	}
+
+	g_array_free(frequencies, TRUE);
+	g_free(tone);
+
+	/* Make sure the output plugin stops prebuffering */
+	tone_ip.output->buffer_free();
+	tone_ip.output->buffer_free();
+
+	g_thread_exit(NULL);
+	return(NULL);
+}
+
+static GArray* tone_filename_parse(const char* filename)
+{
+	GArray *frequencies = g_array_new(FALSE, FALSE, sizeof(double));
+	char **strings, **ptr;
+
+	if (strncmp(filename,"tone://", 7))
+		return NULL;
+
+	filename += 7;
+	strings = g_strsplit(filename, ";", 100);
+
+	for (ptr = strings; *ptr != NULL; ptr++)
+	{
+		double freq = strtod(*ptr, NULL);
+		if (freq >= MIN_FREQ && freq <= MAX_FREQ)
+			g_array_append_val(frequencies, freq);
+	}
+	g_strfreev(strings);
+
+	if (frequencies->len == 0)
+	{
+		g_array_free(frequencies, TRUE);
+		frequencies = NULL;
+	}
+
+	return frequencies;
+}
+
+static char* tone_title(char *filename)
+{
+	GArray *freqs;
+	char* title;
+	gsize i;
+
+	freqs = tone_filename_parse(filename);
+	if (freqs == NULL)
+		return NULL;
+
+	title = g_strdup_printf("%s %.1f Hz", _("Tone Generator: "),
+				g_array_index(freqs, double, 0));
+	for (i = 1; i < freqs->len; i++)
+	{
+		char *old_title;
+		old_title = title;
+		title = g_strdup_printf("%s;%.1f Hz", old_title,
+					g_array_index(freqs, double, i));
+		g_free(old_title);
+	}
+	g_array_free(freqs, TRUE);
+
+	return title;
+}
+	
+
+static void tone_play(char *filename)
+{
+	GArray* frequencies;
+	char *name;
+
+	frequencies = tone_filename_parse(filename);
+	if (frequencies == NULL)
+		return;
+
+ 	going = TRUE;
+	audio_error = FALSE;
+	if (tone_ip.output->open_audio(FMT_S16_NE, OUTPUT_FREQ, 1) == 0)
+	{
+		audio_error = TRUE;
+		going = FALSE;
+		return;
+	}
+
+	name = tone_title(filename);
+	tone_ip.set_info(name, -1, 16 * OUTPUT_FREQ, OUTPUT_FREQ, 1);
+	g_free(name);
+	play_thread = g_thread_create((GThreadFunc)play_loop, frequencies, TRUE, NULL);
+}
+
+static void tone_stop(void)
+{
+	if (going)
+	{
+		going = FALSE;
+		g_thread_join(play_thread);
+		tone_ip.output->close_audio();
+	}
+}
+
+static void tone_pause(short paused)
+{
+	tone_ip.output->pause(paused);
+}
+
+static int tone_get_time(void)
+{
+	if (audio_error)
+		return -2;
+	if (!going && !tone_ip.output->buffer_playing())
+		return -1;
+	return tone_ip.output->output_time();
+}
+
+static void tone_song_info(char *filename, char **title, int *length)
+{
+	*length = -1;
+	*title = tone_title(filename);
+}
+
+static InputPlugin tone_ip = 
+{
+	NULL,
+	NULL,
+	NULL, /* Description */
+	NULL,
+	tone_about,
+	NULL,
+	tone_is_our_file,
+	NULL,
+	tone_play,
+	tone_stop,
+	tone_pause,
+	NULL,
+	NULL,
+	tone_get_time,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	tone_song_info,
+	NULL,
+	NULL
+};
+
+InputPlugin *get_iplugin_info(void)
+{
+	tone_ip.description = g_strdup_printf(_("Tone Generator %s"), PACKAGE_VERSION);
+	return &tone_ip;
+}