Mercurial > audlegacy-plugins
changeset 315:2294f3a6f136 trunk
[svn] Metronom (a.k.a. tact generator) input plugin, ported from XMMS.
author | chainsaw |
---|---|
date | Wed, 29 Nov 2006 14:42:11 -0800 |
parents | 29e5e3b6f1b6 |
children | fb513e10174e |
files | ChangeLog configure.ac src/metronom/Makefile src/metronom/metronom.c |
diffstat | 4 files changed, 320 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Tue Nov 28 12:09:34 2006 -0800 +++ b/ChangeLog Wed Nov 29 14:42:11 2006 -0800 @@ -1,3 +1,11 @@ +2006-11-28 20:09:34 +0000 William Pitcock <nenolod@nenolod.net> + revision [688] + - MirBSD support from <bsiegert -at gmx.de> + + trunk/configure.ac | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + + 2006-11-28 02:10:41 +0000 William Pitcock <nenolod@nenolod.net> revision [682] - be more robust
--- a/configure.ac Tue Nov 28 12:09:34 2006 -0800 +++ b/configure.ac Wed Nov 29 14:42:11 2006 -0800 @@ -85,7 +85,7 @@ dnl These plugins are always built. -INPUT_PLUGINS="tonegen console sexypsf wav cue alac" +INPUT_PLUGINS="tonegen console sexypsf wav cue alac metronom" OUTPUT_PLUGINS="disk_writer" EFFECT_PLUGINS="audiocompress ladspa voice_removal stereo_plugin echo_plugin" GENERAL_PLUGINS="song_change alarm" @@ -1127,6 +1127,7 @@ echo " WavPack 4.31+ (wavpack): $have_wavpack" echo " Musepack support (musepack): $enable_musepack" echo " TrueAudio (tta): $enable_tta" +echo " Metronom: yes" echo echo " General" echo " -------"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/metronom/Makefile Wed Nov 29 14:42:11 2006 -0800 @@ -0,0 +1,14 @@ +include ../../mk/rules.mk +include ../../mk/init.mk + +OBJECTIVE_LIBS = libmetronom$(SHARED_SUFFIX) + +LIBDIR = $(plugindir)/$(INPUT_PLUGIN_DIR) + +SOURCES = metronom.c + +OBJECTS = ${SOURCES:.c=.o} + +CFLAGS += $(PICFLAGS) $(GTK_CFLAGS) -I../../intl -I../.. + +include ../../mk/objective.mk
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/metronom/metronom.c Wed Nov 29 14:42:11 2006 -0800 @@ -0,0 +1,296 @@ +/* + * Copyright 2000 Martin Strauß <mys@faveve.uni-stuttgart.de> + * + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "audacious/plugin.h" +#include "audacious/util.h" +#include <glib.h> +#include <string.h> + +#define MIN_BPM 1 +#define MAX_BPM 512 + +static InputPlugin metronom_ip; + +static gboolean going; +static gboolean audio_error; +static GThread *play_thread; + +struct metronom_struct { + gint bpm; + gint num; + gint den; + gint id; +}; +typedef struct metronom_struct metronom_t; + +#define tact_id_max 12 +gint tact_id[tact_id_max][2]= + { + {1,1}, + {2,2}, + {3,2}, + {4,2}, + {2,4}, + {3,4}, + {4,4}, + {6,4}, + {2,8}, + {3,8}, + {4,8}, + {6,8} + }; +#define tact_form_max 8 +gdouble tact_form[tact_id_max][tact_form_max]= + { + {1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0}, + {1.0,0.5,0.0,0.0,0.0,0.0,0.0,0.0}, + {1.0,0.5,0.5,0.0,0.0,0.0,0.0,0.0}, + {1.0,0.5,0.6,0.5,0.0,0.0,0.0,0.0}, + {1.0,0.5,0.0,0.0,0.0,0.0,0.0,0.0}, + {1.0,0.5,0.5,0.0,0.0,0.0,0.0,0.0}, + {1.0,0.5,0.6,0.5,0.0,0.0,0.0,0.0}, + {1.0,0.5,0.5,0.6,0.5,0.5,0.0,0.0}, + {1.0,0.5,0.0,0.0,0.0,0.0,0.0,0.0}, + {1.0,0.5,0.5,0.0,0.0,0.0,0.0,0.0}, + {1.0,0.5,0.6,0.5,0.0,0.0,0.0,0.0}, + {1.0,0.5,0.5,0.6,0.5,0.5,0.0,0.0} + }; + +static void metronom_about(void) +{ + static GtkWidget *box; + box = xmms_show_message( + "About Metronom", + "A Tact Generator by Martin Strauß <mys@faveve.uni-stuttgart.de>\n\nTo use it, add a URL: tact://beats*num/den\ne.g. tact://77 to play 77 beats per minute\nor tact://60*3/4 to play 60 bpm in 3/4 tacts", "Ok", + FALSE, NULL, NULL); + gtk_signal_connect(GTK_OBJECT(box), "destroy", + GTK_SIGNAL_FUNC(gtk_widget_destroyed), &box); +} + +static int metronom_is_our_file(char *filename) +{ + if (!strncmp(filename, "tact://", 7)) + return TRUE; + return FALSE; +} + +#define BUF_SAMPLES 512 +#define BUF_BYTES BUF_SAMPLES * 2 +#define MAX_AMPL (GINT16_TO_LE((1<<15) - 1)) + +static void* play_loop(void *arg) +{ + gint16 data[BUF_SAMPLES]; + metronom_t *pmetronom=(metronom_t *)arg; + gint i; + + gint16 t = 0,tact; + gint16 datagoal = 0; + gint16 datamiddle = 0; + gint16 datacurrent = datamiddle; + gint16 datalast = datamiddle; + gint16 data_form[tact_form_max]; + gint num; + + tact = 60*44100/pmetronom->bpm; + /* prepare weighted amplitudes */ + for(num=0;num<pmetronom->num;num++){ + data_form[num]=MAX_AMPL*tact_form[pmetronom->id][num]; + } + + num=0; + while (going) + { + for (i = 0; i < BUF_SAMPLES; i++){ + if(t==tact){ + t=0; + datagoal = data_form[num]; + } + else if(t==10) { + datagoal = -data_form[num]; + } + else if(t==25) { + datagoal = data_form[num]; + /* circle through weighted amplitudes */ + num++; + if(num==pmetronom->num)num=0; + } + /* makes curve a little bit smoother */ + data[i]=(datalast+datacurrent+datagoal)/3; + datalast=datacurrent; + datacurrent=data[i]; + if(t > 35) + datagoal=(datamiddle+7*datagoal)/8; + t++; + } + while(metronom_ip.output->buffer_free() < BUF_BYTES && going) + xmms_usleep(30000); + if (going) + produce_audio(metronom_ip.output->written_time(), FMT_S16_LE, 1, BUF_BYTES, data, &going); + } + /* Make sure the output plugin stops prebuffering */ + free(arg); + metronom_ip.output->buffer_free(); + metronom_ip.output->buffer_free(); + g_thread_exit(NULL); +} + +static void metronom_play(char *filename) +{ + gchar *name; + size_t count; + metronom_t *pmetronom; + gint flag,id; + + pmetronom=(metronom_t *)malloc(sizeof(metronom_t)); + if(!pmetronom)return; + + count=sscanf(filename, "tact://%d*%d/%d", &pmetronom->bpm,&pmetronom->num,&pmetronom->den); + if (count != 1 && count !=3)return; + if(!(pmetronom->bpm >= MIN_BPM && pmetronom->bpm <= MAX_BPM))return; + pmetronom->id=0; + if(count==1){ + pmetronom->num=1; + pmetronom->den=1; + } else { + if(pmetronom->num==0 || pmetronom->den==0)return; + flag=FALSE; + for(id=0;(id<tact_id_max && (!flag));id++){ + if(pmetronom->num==tact_id[id][0] && pmetronom->den==tact_id[id][1]){ + flag=TRUE; + pmetronom->id=id; + } + } + if(!flag)return; + } + + going = TRUE; + audio_error = FALSE; + if (metronom_ip.output->open_audio(FMT_S16_LE, 44100, 1) == 0) + { + audio_error = TRUE; + going = FALSE; + return; + } + if(pmetronom->num==1 && pmetronom->den==1){ + name = g_strdup_printf("Tact generator: %d bpm", pmetronom->bpm); + } else { + name = g_strdup_printf("Tact generator: %d bpm %d/%d", pmetronom->bpm,pmetronom->num,pmetronom->den); + } + metronom_ip.set_info(name, -1, 16 * 44100, 44100, 1); + g_free(name); + play_thread = g_thread_create((GThreadFunc)play_loop, pmetronom, TRUE, NULL); +} + +static void metronom_stop(void) +{ + if (going) + { + going = FALSE; + g_thread_join(play_thread); + metronom_ip.output->close_audio(); + } +} + +static void metronom_pause(short paused) +{ + metronom_ip.output->pause(paused); +} + +static int metronom_get_time(void) +{ + if (audio_error) + return -2; + if (!going && !metronom_ip.output->buffer_playing()) + return -1; + return metronom_ip.output->output_time(); +} + +static void metronom_song_info(char *filename, char **title, int *length) +{ + metronom_t metronom; + metronom_t *pmetronom=&metronom; + size_t count; + gint flag,id; + *length = -1; + *title = NULL; + + count=sscanf(filename, "tact://%d*%d/%d", &pmetronom->bpm,&pmetronom->num,&pmetronom->den); + if (count != 1 && count !=3)return; + if(!(pmetronom->bpm >= MIN_BPM && pmetronom->bpm <= MAX_BPM))return; + + if (count == 1) { + pmetronom->num=1; + pmetronom->den=1; + pmetronom->id=0; + } else { + if(pmetronom->num==0 || pmetronom->den==0)return; + flag=FALSE; + for(id=0;(id<tact_id_max && (!flag));id++){ + if(pmetronom->num==tact_id[id][0] && pmetronom->den==tact_id[id][1])flag=TRUE; + } + if(!flag)return; + else pmetronom->id=id; + } + + if(pmetronom->num==1 && pmetronom->den==1){ + *title = g_strdup_printf("Tact generator: %d bpm", pmetronom->bpm); + } else { + *title = g_strdup_printf("Tact generator: %d bpm %d/%d", pmetronom->bpm,pmetronom->num,pmetronom->den); + } +} + + + +static InputPlugin metronom_ip = +{ + NULL, + NULL, + "Tact Generator " VERSION, + NULL, + metronom_about, + NULL, + metronom_is_our_file, + NULL, + metronom_play, + metronom_stop, + metronom_pause, + NULL, + NULL, + metronom_get_time, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + metronom_song_info, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +InputPlugin *get_iplugin_info(void) +{ + return &metronom_ip; +}