diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.am | 40 | ||||
| -rw-r--r-- | src/Makefile.in | 560 | ||||
| -rw-r--r-- | src/lingot-audio.c | 220 | ||||
| -rw-r--r-- | src/lingot-audio.h | 49 | ||||
| -rw-r--r-- | src/lingot-background.xpm | 139 | ||||
| -rw-r--r-- | src/lingot-complex.c | 82 | ||||
| -rw-r--r-- | src/lingot-complex.h | 45 | ||||
| -rw-r--r-- | src/lingot-config-dialog.c | 472 | ||||
| -rw-r--r-- | src/lingot-config-dialog.h | 74 | ||||
| -rw-r--r-- | src/lingot-config.c | 261 | ||||
| -rw-r--r-- | src/lingot-config.h | 109 | ||||
| -rw-r--r-- | src/lingot-core.c | 416 | ||||
| -rw-r--r-- | src/lingot-core.h | 109 | ||||
| -rw-r--r-- | src/lingot-defs.h | 52 | ||||
| -rw-r--r-- | src/lingot-fft.c | 177 | ||||
| -rw-r--r-- | src/lingot-fft.h | 52 | ||||
| -rw-r--r-- | src/lingot-filter.c | 258 | ||||
| -rw-r--r-- | src/lingot-filter.h | 66 | ||||
| -rw-r--r-- | src/lingot-gauge.c | 92 | ||||
| -rw-r--r-- | src/lingot-gauge.h | 46 | ||||
| -rw-r--r-- | src/lingot-i18n.h | 42 | ||||
| -rw-r--r-- | src/lingot-logo.xpm | 343 | ||||
| -rw-r--r-- | src/lingot-mainframe.c | 766 | ||||
| -rw-r--r-- | src/lingot-mainframe.h | 82 | ||||
| -rw-r--r-- | src/lingot-signal.c | 153 | ||||
| -rw-r--r-- | src/lingot-signal.h | 49 | ||||
| -rw-r--r-- | src/lingot.c | 132 |
27 files changed, 4886 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..97a8b32 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,40 @@ +INCLUDES = \ + $(PACKAGE_CFLAGS) $(GTK_CFLAGS) $(ALSA_CFLAGS)\ + -DLINGOT_LOCALEDIR=\""$(datadir)/locale"\" + +AM_CXXFLAGS =\ + -Wall + +bin_PROGRAMS = lingot + +lingot_SOURCES = \ + lingot-fft.c\ + lingot-fft.h\ + lingot-audio.c\ + lingot-audio.h\ + lingot-complex.h\ + lingot-complex.c\ + lingot-config.c\ + lingot-config.h\ + lingot-core.c\ + lingot-core.h\ + lingot-defs.h\ + lingot-config-dialog.c\ + lingot-config-dialog.h\ + lingot-gauge.c\ + lingot-gauge.h\ + lingot-mainframe.c\ + lingot-mainframe.h\ + lingot-filter.c\ + lingot-filter.h\ + lingot-signal.c\ + lingot-signal.h\ + lingot.c\ + lingot-i18n.h + +lingot_LDFLAGS = + +lingot_LDADD = \ + $(PACKAGE_LIBS) $(GTK_LIBS) $(ALSA_LIBS)\ + -lpthread + diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..d4816fc --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,560 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +bin_PROGRAMS = lingot$(EXEEXT) +subdir = src +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(bin_PROGRAMS) +am_lingot_OBJECTS = lingot-fft.$(OBJEXT) lingot-audio.$(OBJEXT) \ + lingot-complex.$(OBJEXT) lingot-config.$(OBJEXT) \ + lingot-core.$(OBJEXT) lingot-config-dialog.$(OBJEXT) \ + lingot-gauge.$(OBJEXT) lingot-mainframe.$(OBJEXT) \ + lingot-filter.$(OBJEXT) lingot-signal.$(OBJEXT) \ + lingot.$(OBJEXT) +lingot_OBJECTS = $(am_lingot_OBJECTS) +am__DEPENDENCIES_1 = +lingot_DEPENDENCIES = $(am__DEPENDENCIES_1) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(lingot_SOURCES) +DIST_SOURCES = $(lingot_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GREP = @GREP@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_CAVES_RULE = @INTLTOOL_CAVES_RULE@ +INTLTOOL_DESKTOP_RULE = @INTLTOOL_DESKTOP_RULE@ +INTLTOOL_DIRECTORY_RULE = @INTLTOOL_DIRECTORY_RULE@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_ICONV = @INTLTOOL_ICONV@ +INTLTOOL_KBD_RULE = @INTLTOOL_KBD_RULE@ +INTLTOOL_KEYS_RULE = @INTLTOOL_KEYS_RULE@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_MSGFMT = @INTLTOOL_MSGFMT@ +INTLTOOL_MSGMERGE = @INTLTOOL_MSGMERGE@ +INTLTOOL_OAF_RULE = @INTLTOOL_OAF_RULE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_PONG_RULE = @INTLTOOL_PONG_RULE@ +INTLTOOL_PROP_RULE = @INTLTOOL_PROP_RULE@ +INTLTOOL_SCHEMAS_RULE = @INTLTOOL_SCHEMAS_RULE@ +INTLTOOL_SERVER_RULE = @INTLTOOL_SERVER_RULE@ +INTLTOOL_SERVICE_RULE = @INTLTOOL_SERVICE_RULE@ +INTLTOOL_SHEET_RULE = @INTLTOOL_SHEET_RULE@ +INTLTOOL_SOUNDLIST_RULE = @INTLTOOL_SOUNDLIST_RULE@ +INTLTOOL_THEME_RULE = @INTLTOOL_THEME_RULE@ +INTLTOOL_UI_RULE = @INTLTOOL_UI_RULE@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_XAM_RULE = @INTLTOOL_XAM_RULE@ +INTLTOOL_XGETTEXT = @INTLTOOL_XGETTEXT@ +INTLTOOL_XML_NOMERGE_RULE = @INTLTOOL_XML_NOMERGE_RULE@ +INTLTOOL_XML_RULE = @INTLTOOL_XML_RULE@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +NO_PREFIX_PACKAGE_DATA_DIR = @NO_PREFIX_PACKAGE_DATA_DIR@ +NO_PREFIX_PACKAGE_DOC_DIR = @NO_PREFIX_PACKAGE_DOC_DIR@ +NO_PREFIX_PACKAGE_HELP_DIR = @NO_PREFIX_PACKAGE_HELP_DIR@ +NO_PREFIX_PACKAGE_MENU_DIR = @NO_PREFIX_PACKAGE_MENU_DIR@ +NO_PREFIX_PACKAGE_PIXMAPS_DIR = @NO_PREFIX_PACKAGE_PIXMAPS_DIR@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_DATA_DIR = @PACKAGE_DATA_DIR@ +PACKAGE_DOC_DIR = @PACKAGE_DOC_DIR@ +PACKAGE_HELP_DIR = @PACKAGE_HELP_DIR@ +PACKAGE_MENU_DIR = @PACKAGE_MENU_DIR@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_PIXMAPS_DIR = @PACKAGE_PIXMAPS_DIR@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +POFILES = @POFILES@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +INCLUDES = \ + $(PACKAGE_CFLAGS) $(GTK_CFLAGS) $(ALSA_CFLAGS)\ + -DLINGOT_LOCALEDIR=\""$(datadir)/locale"\" + +AM_CXXFLAGS = \ + -Wall + +lingot_SOURCES = \ + lingot-fft.c\ + lingot-fft.h\ + lingot-audio.c\ + lingot-audio.h\ + lingot-complex.h\ + lingot-complex.c\ + lingot-config.c\ + lingot-config.h\ + lingot-core.c\ + lingot-core.h\ + lingot-defs.h\ + lingot-config-dialog.c\ + lingot-config-dialog.h\ + lingot-gauge.c\ + lingot-gauge.h\ + lingot-mainframe.c\ + lingot-mainframe.h\ + lingot-filter.c\ + lingot-filter.h\ + lingot-signal.c\ + lingot-signal.h\ + lingot.c\ + lingot-i18n.h + +lingot_LDFLAGS = +lingot_LDADD = \ + $(PACKAGE_LIBS) $(GTK_LIBS) $(ALSA_LIBS)\ + -lpthread + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + || test -f $$p1 \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +lingot$(EXEEXT): $(lingot_OBJECTS) $(lingot_DEPENDENCIES) + @rm -f lingot$(EXEEXT) + $(LINK) $(lingot_LDFLAGS) $(lingot_OBJECTS) $(lingot_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lingot-audio.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lingot-complex.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lingot-config-dialog.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lingot-config.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lingot-core.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lingot-fft.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lingot-filter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lingot-gauge.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lingot-mainframe.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lingot-signal.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lingot.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: install-binPROGRAMS + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libtool ctags distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-binPROGRAMS install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-binPROGRAMS uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/lingot-audio.c b/src/lingot-audio.c new file mode 100644 index 0000000..a0776f6 --- /dev/null +++ b/src/lingot-audio.c @@ -0,0 +1,220 @@ +//-*- C++ -*- +/* + * lingot, a musical instrument tuner. + * + * Copyright (C) 2004-2007 Ibán Cereijo Graña, Jairo Chapela Martínez. + * + * This file is part of lingot. + * + * lingot 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. + * + * lingot 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 lingot; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdio.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <sys/soundcard.h> +#include <stdlib.h> + +#include "lingot-defs.h" +#include "lingot-audio.h" + +LingotAudio * +lingot_audio_new (int channels, int rate, int format, char *fdsp) +{ + LingotAudio *audio; +#ifdef ALSA + snd_pcm_hw_params_t *hw_params; + int err; +#endif + + audio = malloc (sizeof (LingotAudio)); + // int dma = 4; + +#ifdef ALSA + + if ((err = + snd_pcm_open (&audio->capture_handle, "default", SND_PCM_STREAM_CAPTURE, + 0)) < 0) + { + fprintf (stderr, "cannot open audio device %s (%s)\n", + fdsp, snd_strerror (err)); + exit (1); + } + + if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) + { + fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n", + snd_strerror (err)); + exit (1); + } + + if ((err = snd_pcm_hw_params_any (audio->capture_handle, hw_params)) < 0) + { + fprintf (stderr, + "cannot initialize hardware parameter structure (%s)\n", + snd_strerror (err)); + exit (1); + } + + if ((err = + snd_pcm_hw_params_set_access (audio->capture_handle, hw_params, + SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) + { + fprintf (stderr, "cannot set access type (%s)\n", snd_strerror (err)); + exit (1); + } + + if ((err = + snd_pcm_hw_params_set_format (audio->capture_handle, hw_params, + SND_PCM_FORMAT_S16_LE)) < 0) + { + fprintf (stderr, "cannot set sample format (%s)\n", snd_strerror (err)); + exit (1); + } + + if ((err = + snd_pcm_hw_params_set_rate_near (audio->capture_handle, hw_params, + &rate, 0)) < 0) + { + fprintf (stderr, "cannot set sample rate (%s)\n", snd_strerror (err)); + exit (1); + } + + if ((err = + snd_pcm_hw_params_set_channels (audio->capture_handle, hw_params, + channels)) < 0) + { + fprintf (stderr, "cannot set channel count (%s)\n", snd_strerror (err)); + exit (1); + } + + if ((err = snd_pcm_hw_params (audio->capture_handle, hw_params)) < 0) + { + fprintf (stderr, "cannot set parameters (%s)\n", snd_strerror (err)); + exit (1); + } + + snd_pcm_hw_params_free (hw_params); + + if ((err = snd_pcm_prepare (audio->capture_handle)) < 0) + { + fprintf (stderr, "cannot prepare audio interface for use (%s)\n", + snd_strerror (err)); + exit (1); + } + +#else + + audio->dsp = open (fdsp, O_RDONLY); + if (audio->dsp < 0) + { + char buff[80]; + sprintf (buff, "Unable to open audio device %s", fdsp); + perror (buff); + exit (-1); + } + + //if (ioctl(audio->dsp, SOUND_PCM_READ_CHANNELS, &channels) < 0) + if (ioctl (audio->dsp, SNDCTL_DSP_CHANNELS, &channels) < 0) + { + perror ("Error setting number of channels"); + exit (-1); + } + + /* if (ioctl(audio->dsp, SOUND_PCM_WRITE_CHANNELS, &channels) < 0) + { + perror("Error setting number of channels"); + exit(-1); + } */ + + // sample size + //if (ioctl(audio->dsp, SOUND_PCM_SETFMT, &format) < 0) + if (ioctl (audio->dsp, SNDCTL_DSP_SETFMT, &format) < 0) + { + perror ("Error setting bits per sample"); + exit (-1); + } + + int fragment_size = 1; + int DMA_buffer_size = 512; + int param = 0; + + for (param = 0; fragment_size < DMA_buffer_size; param++) + fragment_size <<= 1; + + param |= 0x00ff0000; + + if (ioctl (audio->dsp, SNDCTL_DSP_SETFRAGMENT, ¶m) < 0) + { + perror ("Error setting DMA buffer size"); + exit (-1); + } + + // DMA divisor + /* if (ioctl(audio->dsp, SNDCTL_DSP_SUBDIVIDE, &dma) < 0) + { + perror("Error setting DMA divisor"); + exit(-1); + } + + // Rate de muestreo / reproduccion + if (ioctl(audio->dsp, SOUND_PCM_WRITE_RATE, &rate) < 0) + { + perror("Error setting write rate"); + exit(-1); + } */ + + // if (ioctl(audio->dsp, SOUND_PCM_READ_RATE, &rate) < 0) + if (ioctl (audio->dsp, SNDCTL_DSP_SPEED, &rate) < 0) + { + perror ("Error setting sample rate"); + exit (-1); + } + + /* + // non-blocking reads. + if (fcntl(audio->dsp, F_SETFL, O_NONBLOCK) < 0) + { + perror("Error setting non-blocking reads"); + exit(-1); + } + */ +#endif + + return audio; +} + +void +lingot_audio_destroy (LingotAudio * audio) +{ +#ifdef ALSA + snd_pcm_close (audio->capture_handle); +#else + close (audio->dsp); + free (audio); +#endif +} + +int +lingot_audio_read (LingotAudio * audio, void *buffer, int size) +{ +#ifdef ALSA + return snd_pcm_readi (audio->capture_handle, buffer, size); +#else + return read (audio->dsp, buffer, size); +#endif +} + diff --git a/src/lingot-audio.h b/src/lingot-audio.h new file mode 100644 index 0000000..996c822 --- /dev/null +++ b/src/lingot-audio.h @@ -0,0 +1,49 @@ +//-*- C++ -*- +/* + * lingot, a musical instrument tuner. + * + * Copyright (C) 2004-2007 Ibán Cereijo Graña, Jairo Chapela Martínez. + * + * This file is part of lingot. + * + * lingot 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. + * + * lingot 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 lingot; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LINGOT_AUDIO_H__ +#define __LINGOT_AUDIO_H__ + + +//#define ALSA + +#ifdef ALSA +#include <alsa/asoundlib.h> +#endif + +typedef struct _LingotAudio LingotAudio; + +struct _LingotAudio + { + #ifdef ALSA + snd_pcm_t *capture_handle; + #else + int dsp; // file handler. + #endif + }; + +LingotAudio* lingot_audio_new(int channels, int rate, int format, char* fdsp); +void lingot_audio_destroy(LingotAudio* audio); +int lingot_audio_read(LingotAudio* audio, void* buffer, int size); + +#endif diff --git a/src/lingot-background.xpm b/src/lingot-background.xpm new file mode 100644 index 0000000..7cac040 --- /dev/null +++ b/src/lingot-background.xpm @@ -0,0 +1,139 @@ +//-*- C++ -*- +/* + * lingot, a musical instrument tuner. + * + * Copyright (C) 2004-2007 Ibán Cereijo Graña, Jairo Chapela Martínez. + * + * This file is part of lingot. + * + * lingot 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. + * + * lingot 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 lingot; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* XPM */ +static char * background2_xpm[] = { +"160 100 14 1", +" c None", +". c #000000", +"+ c #EEEEEE", +"@ c #8B898B", +"# c #BDEEBD", +"$ c #EEBABD", +"% c #B9B9B9", +"& c #4F4F4F", +"* c #848484", +"= c #6A6A6A", +"- c #D3D3D3", +"; c #353535", +"> c #9E9E9E", +", c #1B1B1B", +"................................................................................................................................................................", +".++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@@@@@@@@@@@@@@@@@@@+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@@@@@@+++++++++++++++++++@@@@@@+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.", +".+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@@@@@+++++++++++++++++++++++++++++++@@@@@++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.", +".+++++++++++++++++++++++++++++++++++++++++++++++++++++++@@@@+++++++++++++++++++++++++++++++++++++++++@@@@++++++++++++++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++++++++++@@@+++++++++++++++++++++++++++++++++++++++++++++++++@@@+++++++++++++++++++++++++++++++++++++++++++++++++++.", +".+++++++++++++++++++++++++++++++++++++++++++++++++@@@+++++++++++++++++++++++++++++++++++++++++++++++++++++++@@@++++++++++++++++++++++++++++++++++++++++++++++++.", +".+++++++++++++++++++++++++++++++++++++++++++++++@@+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@@++++++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++@@@+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@@@+++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++@@+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@@+++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++@@+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@@+++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++@@+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@@+++++++++++++++++++++++++++++++++++++.", +".+++++++++++++++++++++++++++++++++++++@+++++++++++++++++++++++++++++++++++++++++#+++++++++++++++++++++++++++++++++++++++++@++++++++++++++++++++++++++++++++++++.", +".+++++++++++++++++++++++++++++++++++@@++++++++++++++++++++++++++++++$$$$$###############$$$$$++++++++++++++++++++++++++++++@@++++++++++++++++++++++++++++++++++.", +".+++++++++++++++++++++++++++++++++@@+++++++++++++++++++++++++++$$$$$$$$$$###############$$$$$$$$$$+++++++++++++++++++++++++++@@++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++@+++++++++++++++++++++++++$$$$$$$$$$$$$$###############$$$$$$$$$$$$$++++++++++++++++++++++++++@+++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++@@+++++++++++++++++++++++$$$$$$$$$$$$$$$$$###############$$$$$$$$$$$$$$$$$+++++++++++++++++++++++@@+++++++++++++++++++++++++++++.", +".+++++++++++++++++++++++++++++@+++++++++++++++++++++++$$$$$$$$$$$$$$$$$$$###############$$$$$$$$$$$$$$$$$$$+++++++++++++++++++++++@++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++@+++++++++++++++++++++$$$$$$$$$$$$$$$$$$$$$$#######+#######$$$$$$$$$$$$$$$$$$$$$$+++++++++++++++++++++@+++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++@@++++++++++++++++++++$$$$$$$$$$$$$$$$$$$$+++++++++++++++++++++++$$$$$$$$$$$$$$$$$$$$++++++++++++++++++++@@+++++++++++++++++++++++++.", +".+++++++++++++++++++++++++@++++++++++++++++++++$$$$$$$$$$$$$$$$$+++++++++++++++++++++++++++++++++$$$$$$$$$$$$$$$$$++++++++++++++++++++@++++++++++++++++++++++++.", +".++++++++++++++++++++++++@+++++++++++++++++++$$$$$$$$$$$$$$$+++++++++++++++++++++++++++++++++++++++++$$$$$$$$$$$$$$$+++++++++++++++++++@+++++++++++++++++++++++.", +".+++++++++++++++++++++++@++++++++++++++++++$$$$$$$$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$$$$$$$$++++++++++++++++++@++++++++++++++++++++++.", +".++++++++++++++++++++++@+++++++++++++++++$$$$$$$$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$$$$$$$$+++++++++++++++++@+++++++++++++++++++++.", +".++++++++++++++++++++@@+++++++++++++++++$$$$$$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$$$$$$+++++++++++++++++@@+++++++++++++++++++.", +".+++++++++++++++++++@+++++++++++++++++$$$$$$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$$$$$$+++++++++++++++++@++++++++++++++++++.", +".++++++++++++++++++@+++++++++++++++++$$$$$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$$$$$+++++++++++++++++@+++++++++++++++++.", +".+++++++++++++++++@++++++++++++++++$$$$$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$$$$+++++++++++++++++@++++++++++++++++.", +".++++++++++++++++@++++++++++++++++$$$$$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$$$$$++++++++++++++++@+++++++++++++++.", +".++++++++++++++++@+++++++++++++++$$$$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$$$$+++++++++++++++@+++++++++++++++.", +".+++++++++++++++@+++++++++++++++$$$$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$$$$+++++++++++++++@++++++++++++++.", +".++++++++++++++@+++++++++++++++$$$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$$$+++++++++++++++@+++++++++++++.", +".+++++++++++++@+++++++++++++++$$$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$$$+++++++++++++++@++++++++++++.", +".++++++++++++@++++++++++++++$$$$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$$$$++++++++++++++@+++++++++++.", +".+++++++++++@++++++++++++++$$$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$$$++++++++++++++@++++++++++.", +".+++++++++++@+++++++++++++$$$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$$$+++++++++++++@++++++++++.", +".++++++++++@++++++++++++++$$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$$++++++++++++++@+++++++++.", +".+++++++++@++++++++++++++$$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$$++++++++++++++@++++++++.", +".++++++++@++++++++++++++$$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$$++++++++++++++@+++++++.", +".++++++++@+++++++++++++$$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$$+++++++++++++@+++++++.", +".+++++++@+++++++++++++$$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$$+++++++++++++@++++++.", +".++++++@+++++++++++++$$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$$+++++++++++++@+++++.", +".++++++@++++++++++++$$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$+++++++++++++@+++++.", +".+++++@+++++++++++++$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$+++++++++++++@++++.", +".+++++@++++++++++++$$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$$++++++++++++@++++.", +".++++++@@+++++++++$$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$$+++++++++@@+++++.", +".++++++++@@+++++++$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$+++++++@@+++++++.", +".++++++++++@@++++$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$++++@@+++++++++.", +".++++++++++++@++$$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$$++@+++++++++++.", +".+++++++++++++@@$$$$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$$$$@@++++++++++++.", +".+++++++++++++++@@$$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$$@@++++++++++++++.", +".+++++++++++++++++@$$$+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++$$$@++++++++++++++++.", +".++++++++++++++++++@@+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@@+++++++++++++++++.", +".++++++++++++++++++++@@+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@@+++++++++++++++++++.", +".++++++++++++++++++++++@@+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@@+++++++++++++++++++++.", +".++++++++++++++++++++++++@+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@+++++++++++++++++++++++.", +".+++++++++++++++++++++++++@@+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@@++++++++++++++++++++++++.", +".+++++++++++++++++++++++++++@@+++++++++++++++++++++++++++++++++++++++++++++@@@@@@@@@@@+++++++++++++++++++++++++++++++++++++++++++++@@++++++++++++++++++++++++++.", +".+++++++++++++++++++++++++++++@++++++++++++++++++++++++++++++++++++++++@@@@+++++++++++@@@@++++++++++++++++++++++++++++++++++++++++@++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++@@++++++++++++++++++++++++++++++++++++@@+++++++++++++++++++@@++++++++++++++++++++++++++++++++++++@@+++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++@@+++++++++++++++++++++++++++++++@@@+++++++++++++++++++++++@@@+++++++++++++++++++++++++++++++@@+++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++@@++++++++++++++++++++++++++++@+++++++++++++++++++++++++++++@++++++++++++++++++++++++++++@@+++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++@+++++++++++++++++++++++++@@+++++++++++++++++++++++++++++++@@+++++++++++++++++++++++++@+++++++++++++++++++++++++++++++++++.", +".+++++++++++++++++++++++++++++++++++++@@++++++++++++++++++++++@+++++++++++++++++++++++++++++++++++@++++++++++++++++++++++@@++++++++++++++++++++++++++++++++++++.", +".+++++++++++++++++++++++++++++++++++++++@@+++++++++++++++++++@+++++++++++++++++++++++++++++++++++++@+++++++++++++++++++@@++++++++++++++++++++++++++++++++++++++.", +".+++++++++++++++++++++++++++++++++++++++++@+++++++++++++++++@+++++++++++++++++++++++++++++++++++++++@+++++++++++++++++@++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++@@++++++++++++++@+++++++++++++++++++++++++++++++++++++++++@++++++++++++++@@+++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++@@+++++++++++@+++++++++++++++++++++++++++++++++++++++++++@+++++++++++@@+++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++++@@++++++++@+++++++++++++++++++++++++++++++++++++++++++++@++++++++@@+++++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++++++@++++++@+++++++++++++++++++++++++++++++++++++++++++++++@++++++@+++++++++++++++++++++++++++++++++++++++++++++++.", +".+++++++++++++++++++++++++++++++++++++++++++++++++@@+++@+++++++++++++++++++++++++++++++++++++++++++++++++@+++@@++++++++++++++++++++++++++++++++++++++++++++++++.", +".+++++++++++++++%&&&++*&&%++++=&%+*-++++++++++++++++@@+@+++++++++++++++++++++++++++++++++++++++++++++++++@+@@++++++++++++++++++++++++*&&*+-=&=-+++-&=-+=+++++++.", +".+++++++++++++++=-+++**+-;-++=%+&-;+++++++++++++++++++@+++++++++++++++++++++++++++++++++++++++++++++++++++@++++++++++++++++++++++++++&++++;-+%;+++&--=**+++++++.", +".+++++++++++++++&%>++&+++>>++=>-;=%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%%+++&>%++&+++&+++;->=;++++++++.", +".+++++++++++++++.*>;-&+++>>+++=&-;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>>++>,>*&+&+++&+++-&=>*++++++++.", +".+++++++++++%>>++++-=&+++>>+++++*%==-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%&;;&*++++*%&+++&++++++&-&*++++++.", +".+++++++++++%>>%%+++&&+++*>+++++&=>-=+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>>++*+++>>&+++;+++++%*;-*%+++++.", +".++++++++++++++-;-+&%*=+-,-++++**=--=+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>>++>&+-;+;%+>;+++++;-&+*%+++++.", +".+++++++++++++++-&&%++*&&%+++++=+-==-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--+++>&=-+-=&=-++++-*+%&*++++++.", +".++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.", +".++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.", +"................................................................................................................................................................"}; diff --git a/src/lingot-complex.c b/src/lingot-complex.c new file mode 100644 index 0000000..9d3b03a --- /dev/null +++ b/src/lingot-complex.c @@ -0,0 +1,82 @@ +//-*- C++ -*- +/* + * lingot, a musical instrument tuner. + * + * Copyright (C) 2004-2007 Ibán Cereijo Graña, Jairo Chapela Martínez. + * + * This file is part of lingot. + * + * lingot 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. + * + * lingot 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 lingot; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "lingot-complex.h" + +/** + * addition. All parameters are overlapables. + */ +void lingot_complex_add(LingotComplex* a, LingotComplex* b, LingotComplex* c) + { + c->r = a->r + b->r; + c->i = a->i + b->i; + } + +/** + * substraction. All parameters are overlapables. + */ +void lingot_complex_sub(LingotComplex* a, LingotComplex* b, LingotComplex* c) + { + c->r = a->r - b->r; + c->i = a->i - b->i; + } + +/** + * multiplication. All parameters are overlapables. + */ +void lingot_complex_mul(LingotComplex* a, LingotComplex* b, LingotComplex* c) + { + if ((c != a) && (c != b)) + { + c->r = a->r*b->r- a->i*b->i; + c->i = a->i*b->r+ a->r*b->i; + } + else + { + LingotComplex r; + r.r = a->r*b->r- a->i*b->i; + r.i = a->i*b->r+ a->r*b->i; + *c = r; + } + } + +/** + * division. All parameters are overlapables. + */ +void lingot_complex_div(LingotComplex* a, LingotComplex* b, LingotComplex* c) + { + FLT bm2 = b->r*b->r + b->i*b->i; + + if ((c != a) && (c != b)) + { + c->r = (a->r*b->r+ a->i*b->i)/bm2; + c->i = (a->i*b->r- a->r*b->i)/bm2; + } + else + { + LingotComplex r; + r.r = (a->r*b->r+ a->i*b->i)/bm2; + r.i = (a->i*b->r- a->r*b->i)/bm2; + *c = r; + } + } diff --git a/src/lingot-complex.h b/src/lingot-complex.h new file mode 100644 index 0000000..e764ed0 --- /dev/null +++ b/src/lingot-complex.h @@ -0,0 +1,45 @@ +//-*- C++ -*-
+/*
+ * lingot, a musical instrument tuner.
+ *
+ * Copyright (C) 2004-2007 Ibán Cereijo Graña, Jairo Chapela Martínez.
+ *
+ * This file is part of lingot.
+ *
+ * lingot 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.
+ *
+ * lingot 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 lingot; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _LINGOT_COMPLEX_H_
+#define _LINGOT_COMPLEX_H_
+
+#include <math.h>
+#include "lingot-defs.h"
+
+// single complex arithmetic :)
+
+typedef struct _LingotComplex LingotComplex;
+
+struct _LingotComplex
+ {
+ FLT r;
+ FLT i;
+ };
+
+void lingot_complex_add(LingotComplex* a, LingotComplex* b, LingotComplex* c);
+void lingot_complex_sub(LingotComplex* a, LingotComplex* b, LingotComplex* c);
+void lingot_complex_mul(LingotComplex* a, LingotComplex* b, LingotComplex* c);
+void lingot_complex_div(LingotComplex* a, LingotComplex* b, LingotComplex* c);
+
+#endif
diff --git a/src/lingot-config-dialog.c b/src/lingot-config-dialog.c new file mode 100644 index 0000000..c0c707f --- /dev/null +++ b/src/lingot-config-dialog.c @@ -0,0 +1,472 @@ +//-*- C++ -*- +/* + * lingot, a musical instrument tuner. + * + * Copyright (C) 2004-2007 Ibán Cereijo Graña, Jairo Chapela Martínez. + * + * This file is part of lingot. + * + * lingot 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. + * + * lingot 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 lingot; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <unistd.h> +#include <signal.h> + +#include "lingot-defs.h" + +#include "lingot-core.h" +#include "lingot-config.h" +#include "lingot-mainframe.h" +#include "lingot-config-dialog.h" +#include "lingot-i18n.h" + +/* button press event attention routine. */ +void lingot_config_dialog_callback_click(GtkButton *button, + LingotConfigDialog *dialog) + { + if ((GtkWidget*)button == dialog->button_ok) + { + lingot_config_dialog_apply(dialog); + lingot_config_save(dialog->conf, CONFIG_FILE_NAME); + lingot_config_dialog_close(dialog); + } + else if ((GtkWidget*)button == dialog->button_cancel) + { + lingot_mainframe_change_config(dialog->mainframe, dialog->conf_old); // restore old configuration. + lingot_config_dialog_close(dialog); + } + else if ((GtkWidget*)button == dialog->button_apply) + { + lingot_config_dialog_apply(dialog); + lingot_config_dialog_rewrite(dialog); + } + else if ((GtkWidget*)button == dialog->button_default) + { + lingot_config_reset(dialog->conf); + lingot_config_dialog_rewrite(dialog); + } + } + +void lingot_config_dialog_callback_close(GtkWidget *widget, + LingotConfigDialog *dialog) + { + gtk_widget_destroy(dialog->win); + lingot_config_dialog_destroy(dialog); + } + +void lingot_config_dialog_callback_change_sample_rate(GtkWidget *widget, + LingotConfigDialog *dialog) + { + char buff[20]; + float sample_rate =atof(gtk_combo_box_get_active_text(GTK_COMBO_BOX(dialog->combo_sample_rate))); + float oversampling= + gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(dialog->spin_oversampling)); + sprintf(buff, " = %0.1f", sample_rate/oversampling); + gtk_label_set_text ( GTK_LABEL(dialog->label_sample_rate), buff); + } + +void lingot_config_dialog_callback_change_a_frequence(GtkWidget *widget, + LingotConfigDialog *dialog) + { + char buff[20]; + + float root_freq = 440.0*pow(2.0, gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(dialog->spin_root_frequency_error))/1200.0); + sprintf(buff, "%% = %0.2f", root_freq); + gtk_label_set_text ( GTK_LABEL(dialog->label_root_frequency), buff); + } + +void lingot_config_dialog_combo_select_value(GtkWidget* combo, int value) + { + + GtkTreeModel* model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)); + GtkTreeIter iter; + + gboolean valid = gtk_tree_model_get_iter_first (model, &iter); + + while (valid) + { + gchar *str_data; + gtk_tree_model_get (model, &iter, 0, &str_data, -1); + if (atoi(str_data) == value) + gtk_combo_box_set_active_iter(GTK_COMBO_BOX(combo), &iter); + g_free (str_data); + valid = gtk_tree_model_iter_next (model, &iter); + } + } + +void lingot_config_dialog_rewrite(LingotConfigDialog* dialog) + { + gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->spin_calculation_rate), dialog->conf->calculation_rate); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->spin_visualization_rate), dialog->conf->visualization_rate); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->spin_oversampling), dialog->conf->oversampling); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->spin_root_frequency_error), dialog->conf->root_frequency_error); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->spin_temporal_window), dialog->conf->temporal_window); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->spin_noise_threshold), dialog->conf->noise_threshold_db); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->spin_dft_number), dialog->conf->dft_number); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->spin_dft_size), dialog->conf->dft_size); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->spin_peak_number), dialog->conf->peak_number); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->spin_peak_order), dialog->conf->peak_order); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->spin_peak_rejection_relation), dialog->conf->peak_rejection_relation_db); + lingot_config_dialog_combo_select_value(dialog->combo_fft_size, + (int) dialog->conf->fft_size); + lingot_config_dialog_combo_select_value(dialog->combo_sample_rate, + (int) dialog->conf->sample_rate); + lingot_config_dialog_callback_change_sample_rate(NULL, dialog); + lingot_config_dialog_callback_change_a_frequence(NULL, dialog); + } + +LingotConfigDialog* lingot_config_dialog_new(LingotMainFrame* frame) + { + GtkWidget* vertical_box; + GtkWidget* frame1; + GtkWidget* tab1; + GtkWidget* frame2; + GtkWidget* tab2; + GtkWidget* box; + char buff[80]; + LingotConfigDialog* dialog = malloc(sizeof(LingotConfigDialog)); + + dialog->mainframe = frame; + dialog->conf = lingot_config_new(); + dialog->conf_old = lingot_config_new(); + + // config copy + *dialog->conf = *frame->conf; + *dialog->conf_old = *frame->conf; + + dialog->win = gtk_dialog_new_with_buttons (_("lingot configuration"), + GTK_WINDOW(frame->win), 0, NULL); + + gtk_container_set_border_width(GTK_CONTAINER(dialog->win), 6); + + // items vertically displayed + vertical_box = gtk_vbox_new(FALSE, 6); + gtk_container_add(GTK_CONTAINER (GTK_DIALOG(dialog->win)->vbox), vertical_box); + + frame1 = gtk_frame_new(_("General parameters")); + gtk_box_pack_start_defaults(GTK_BOX(vertical_box), frame1); + + tab1 = gtk_table_new(5, 3, FALSE); + int row = 0; + + gtk_table_set_col_spacings(GTK_TABLE(tab1), 20); + gtk_table_set_row_spacings(GTK_TABLE(tab1), 3); + gtk_container_set_border_width(GTK_CONTAINER(tab1), 5); + + gtk_container_add(GTK_CONTAINER(frame1), tab1); + + // -------------------------------------------------------------------------- + + dialog->spin_calculation_rate = gtk_spin_button_new( + (GtkAdjustment*)gtk_adjustment_new(dialog->conf->calculation_rate, 1.0, + 60.0, 0.5, 10.0, 15.0), 0.5, 1); + gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(dialog->spin_calculation_rate), TRUE); + gtk_table_attach_defaults(GTK_TABLE(tab1), + gtk_label_new(_("Calculation rate")), 0, 1, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(tab1), dialog->spin_calculation_rate, 1, 2, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(tab1), gtk_label_new(_("Hz")), 2, 3, row, row + 1); + row++; + + // -------------------------------------------------------------------------- + + dialog->spin_visualization_rate =gtk_spin_button_new( + (GtkAdjustment*)gtk_adjustment_new(dialog->conf->visualization_rate, + 1.0, 60.0, 0.5, 10.0, 15.0), 0.5, 1); + gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(dialog->spin_visualization_rate), TRUE); + gtk_table_attach_defaults(GTK_TABLE(tab1), + gtk_label_new(_("Visualization rate")), 0, 1, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(tab1), dialog->spin_visualization_rate, 1, 2, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(tab1), gtk_label_new(_("Hz")), 2, 3, row, row + 1); + row++; + + // -------------------------------------------------------------------------- + + dialog->combo_fft_size = gtk_combo_box_new_text(); + gtk_combo_box_append_text(GTK_COMBO_BOX(dialog->combo_fft_size), "256"); + gtk_combo_box_append_text(GTK_COMBO_BOX(dialog->combo_fft_size), "512"); + gtk_combo_box_append_text(GTK_COMBO_BOX(dialog->combo_fft_size), "1024"); + gtk_combo_box_append_text(GTK_COMBO_BOX(dialog->combo_fft_size), "2048"); + gtk_combo_box_append_text(GTK_COMBO_BOX(dialog->combo_fft_size), "4096"); + lingot_config_dialog_combo_select_value(dialog->combo_fft_size, + (int) dialog->conf->fft_size); + + gtk_table_attach_defaults(GTK_TABLE(tab1), gtk_label_new(_("FFT size")), 0, 1, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(tab1), dialog->combo_fft_size, 1, 2, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(tab1), gtk_label_new(_("samples")), 2, 3, row, row + 1); + row++; + + // -------------------------------------------------------------------------- + + dialog->spin_noise_threshold =gtk_spin_button_new( + (GtkAdjustment*)gtk_adjustment_new(dialog->conf->noise_threshold_db, + -30.0, 60.0, 0.1, 0.1, 0.1), 0.1, 1); + gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(dialog->spin_noise_threshold), TRUE); + gtk_spin_button_set_digits(GTK_SPIN_BUTTON(dialog->spin_noise_threshold), 1) ; + + gtk_table_attach_defaults(GTK_TABLE(tab1), + gtk_label_new(_("Noise threshold")), 0, 1, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(tab1), gtk_label_new(_("dB")), 2, 3, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(tab1), dialog->spin_noise_threshold, 1, 2, row, row + 1); + row++; + + // -------------------------------------------------------------------------- + + box = gtk_hbox_new (FALSE, FALSE); + + dialog->combo_sample_rate = gtk_combo_box_new_text(); + gtk_combo_box_append_text(GTK_COMBO_BOX(dialog->combo_sample_rate), "8000"); + gtk_combo_box_append_text(GTK_COMBO_BOX(dialog->combo_sample_rate), "11025"); + gtk_combo_box_append_text(GTK_COMBO_BOX(dialog->combo_sample_rate), "22050"); + gtk_combo_box_append_text(GTK_COMBO_BOX(dialog->combo_sample_rate), "44100"); + + lingot_config_dialog_combo_select_value(dialog->combo_sample_rate, + (int) dialog->conf->sample_rate); + + dialog->spin_oversampling = gtk_spin_button_new( + (GtkAdjustment*) gtk_adjustment_new(dialog->conf->oversampling, 1.0, + 30.0, 1.0, 10.0, 15.0), 1.0, 1); + + gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(dialog->spin_oversampling), TRUE); + gtk_spin_button_set_digits(GTK_SPIN_BUTTON(dialog->spin_oversampling), 0) ; + + sprintf(buff, " = %0.1f", atof(gtk_combo_box_get_active_text(GTK_COMBO_BOX(dialog->combo_sample_rate))) + /gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(dialog->spin_oversampling))); + dialog->label_sample_rate = gtk_label_new(buff); + + gtk_box_pack_start (GTK_BOX(box), dialog->combo_sample_rate, FALSE, FALSE, FALSE); + gtk_box_pack_start (GTK_BOX(box), gtk_label_new(" / "), FALSE, FALSE, FALSE); + gtk_box_pack_start (GTK_BOX(box), dialog->spin_oversampling, FALSE, FALSE, FALSE); + gtk_box_pack_start (GTK_BOX(box), dialog->label_sample_rate, FALSE, FALSE, FALSE); + + gtk_signal_connect(GTK_OBJECT(dialog->combo_sample_rate), "changed", + GTK_SIGNAL_FUNC (lingot_config_dialog_callback_change_sample_rate), dialog); + + gtk_signal_connect (GTK_OBJECT (dialog->spin_oversampling), "value_changed", + GTK_SIGNAL_FUNC (lingot_config_dialog_callback_change_sample_rate), dialog); + + gtk_table_attach_defaults(GTK_TABLE(tab1), + gtk_label_new(_("Sample rate")), 0, 1, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(tab1), box, 1, 2, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(tab1), gtk_label_new(_("Hz")), 2, 3, row, row + 1); + row++; + + // -------------------------------------------------------------------------- + + frame2 = gtk_frame_new(_("Advanced parameters")); + gtk_box_pack_start_defaults(GTK_BOX(vertical_box), frame2); + + tab2 = gtk_table_new(7, 3, FALSE); + row = 0; + + gtk_table_set_col_spacings(GTK_TABLE(tab2), 20); + gtk_table_set_row_spacings(GTK_TABLE(tab2), 3); + gtk_container_set_border_width(GTK_CONTAINER(tab2), 5); + + gtk_container_add(GTK_CONTAINER(frame2), tab2); + + // -------------------------------------------------------------------------- + + box = gtk_hbox_new (TRUE, FALSE); + + dialog->spin_root_frequency_error = gtk_spin_button_new( + (GtkAdjustment*)gtk_adjustment_new(dialog->conf->root_frequency_error, + -500.0, +500.0, 1.0, 10.0, 15.0), 1.0, 1); + + gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(dialog->spin_root_frequency_error), TRUE); + gtk_spin_button_set_digits(GTK_SPIN_BUTTON(dialog->spin_root_frequency_error), 0) ; + + gtk_box_pack_start (GTK_BOX(box), gtk_label_new(_(" A (440 Hz) + ")), FALSE, FALSE, FALSE); + gtk_box_pack_start (GTK_BOX(box), dialog->spin_root_frequency_error, FALSE, TRUE, FALSE); + + sprintf(buff, "%% = %0.2f", dialog->conf->root_frequency); + dialog->label_root_frequency = gtk_label_new(_(buff)); + + gtk_box_pack_start (GTK_BOX(box), dialog->label_root_frequency, FALSE, FALSE, FALSE); + + gtk_signal_connect (GTK_OBJECT (dialog->spin_root_frequency_error), "value_changed", + GTK_SIGNAL_FUNC (lingot_config_dialog_callback_change_a_frequence), dialog); + + gtk_table_attach_defaults(GTK_TABLE(tab2), + gtk_label_new(_("Root frequency")), 0, 1, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(tab2), box, 1, 2, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(tab2), gtk_label_new(_("Hz")), 2, 3, row, row + 1); + row++; + + // -------------------------------------------------------------------------- + + dialog->spin_temporal_window =gtk_spin_button_new( + (GtkAdjustment*)gtk_adjustment_new(dialog->conf->temporal_window, 0.0, + 15.0, 0.005, 0.1, 0.1), 0.005, 1); + gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(dialog->spin_temporal_window), TRUE); + gtk_spin_button_set_digits(GTK_SPIN_BUTTON(dialog->spin_temporal_window), 3) ; + + gtk_table_attach_defaults(GTK_TABLE(tab2), + gtk_label_new(_("Temporal window")), 0, 1, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(tab2), gtk_label_new(_("seconds")), 2, 3, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(tab2), dialog->spin_temporal_window, 1, 2, row, row + 1); + row++; + + // -------------------------------------------------------------------------- + + dialog->spin_dft_number =gtk_spin_button_new( + (GtkAdjustment*)gtk_adjustment_new(dialog->conf->dft_number, 0.0, 10.0, + 1.0, 1.0, 1.0), 1.0, 1); + gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(dialog->spin_dft_number), TRUE); + gtk_spin_button_set_digits(GTK_SPIN_BUTTON(dialog->spin_dft_number), 0) ; + + gtk_table_attach_defaults(GTK_TABLE(tab2), + gtk_label_new(_("DFT number")), 0, 1, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(tab2), dialog->spin_dft_number, 1, 2, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(tab2), gtk_label_new(_("DFTs")), 2, 3, row, row + 1); + row++; + + // -------------------------------------------------------------------------- + + dialog->spin_dft_size =gtk_spin_button_new( + (GtkAdjustment*)gtk_adjustment_new(dialog->conf->dft_size, 4.0, 100.0, + 1.0, 1.0, 1.0), 1.0, 1); + gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(dialog->spin_dft_size), TRUE); + gtk_spin_button_set_digits(GTK_SPIN_BUTTON(dialog->spin_dft_size), 0) ; + + gtk_table_attach_defaults(GTK_TABLE(tab2), gtk_label_new(_("DFT size")), 0, 1, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(tab2), gtk_label_new(_("samples")), 2, 3, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(tab2), dialog->spin_dft_size, 1, 2, row, row + 1); + row++; + + // -------------------------------------------------------------------------- + + dialog->spin_peak_number =gtk_spin_button_new( + (GtkAdjustment*)gtk_adjustment_new(dialog->conf->peak_number, 1.0, + 10.0, 1.0, 1.0, 1.0), 1.0, 1); + gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(dialog->spin_peak_number), TRUE); + gtk_spin_button_set_digits(GTK_SPIN_BUTTON(dialog->spin_peak_number), 0) ; + + gtk_table_attach_defaults(GTK_TABLE(tab2), gtk_label_new(_("Peak number")), 0, 1, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(tab2), dialog->spin_peak_number, 1, 2, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(tab2), gtk_label_new(_("peaks")), 2, 3, row, row + 1); + row++; + + // -------------------------------------------------------------------------- + + dialog->spin_peak_order = gtk_spin_button_new( + (GtkAdjustment*)gtk_adjustment_new(dialog->conf->peak_order, 1.0, 5.0, + 1.0, 1.0, 1.0), 1.0, 1); + gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(dialog->spin_peak_order), TRUE); + gtk_spin_button_set_digits(GTK_SPIN_BUTTON(dialog->spin_peak_order), 0) ; + + gtk_table_attach_defaults(GTK_TABLE(tab2), gtk_label_new(_("Peak order")), 0, 1, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(tab2), dialog->spin_peak_order, 1, 2, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(tab2), gtk_label_new(_("samples")), 2, 3, row, row + 1); + row++; + + // -------------------------------------------------------------------------- + + dialog->spin_peak_rejection_relation + = gtk_spin_button_new( + (GtkAdjustment*)gtk_adjustment_new( + dialog->conf->peak_rejection_relation_db, 2.0, 40.0, 0.1, 1.0, + 1.0), 0.1, 1); + gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(dialog->spin_peak_rejection_relation), TRUE); + gtk_spin_button_set_digits(GTK_SPIN_BUTTON(dialog->spin_peak_rejection_relation), 1); + + gtk_table_attach_defaults(GTK_TABLE(tab2), + gtk_label_new(_("Rejection peak relation")), 0, 1, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(tab2), dialog->spin_peak_rejection_relation, 1, 2, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(tab2), gtk_label_new(_("dB")), 2, 3, row, row + 1); + row++; + + // -------------------------------------------------------------------------- + + dialog->button_ok = gtk_button_new_from_stock(GTK_STOCK_OK); + dialog->button_cancel = gtk_button_new_from_stock(GTK_STOCK_CANCEL); + dialog->button_apply = gtk_button_new_from_stock(GTK_STOCK_APPLY); + dialog->button_default = gtk_button_new_with_label(_("Default config")); + + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog->win)->action_area), dialog->button_default, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog->win)->action_area), dialog->button_apply, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog->win)->action_area), dialog->button_ok, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog->win)->action_area), dialog->button_cancel, TRUE, TRUE, 0); + + g_signal_connect(GTK_OBJECT(dialog->button_default), "clicked", GTK_SIGNAL_FUNC(lingot_config_dialog_callback_click), dialog); + g_signal_connect(GTK_OBJECT(dialog->button_apply), "clicked", GTK_SIGNAL_FUNC(lingot_config_dialog_callback_click), dialog); + g_signal_connect(GTK_OBJECT(dialog->button_ok), "clicked", GTK_SIGNAL_FUNC(lingot_config_dialog_callback_click), dialog); + g_signal_connect(GTK_OBJECT(dialog->button_cancel), "clicked", GTK_SIGNAL_FUNC(lingot_config_dialog_callback_click), dialog); + + g_signal_connect(GTK_OBJECT(dialog->win), "destroy", GTK_SIGNAL_FUNC(lingot_config_dialog_callback_close), dialog); + + lingot_config_dialog_rewrite(dialog); + gtk_window_set_resizable(GTK_WINDOW(dialog->win), FALSE); + gtk_widget_show_all(dialog->win); + + return dialog; + } + +void lingot_config_dialog_destroy(LingotConfigDialog* dialog) + { + dialog->mainframe->config_dialog = NULL; + lingot_config_destroy(dialog->conf); + lingot_config_destroy(dialog->conf_old); + + //gtk_widget_destroy(dialog->win); + free(dialog); + } + +void lingot_config_dialog_apply(LingotConfigDialog* dialog) + { + GtkWidget* message_dialog; + + dialog->conf->root_frequency_error = gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(dialog->spin_root_frequency_error)); + dialog->conf->calculation_rate = gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(dialog->spin_calculation_rate)); + dialog->conf->visualization_rate = gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(dialog->spin_visualization_rate)); + dialog->conf->temporal_window = gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(dialog->spin_temporal_window)); + dialog->conf->noise_threshold_db = gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(dialog->spin_noise_threshold)); + dialog->conf->oversampling + = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(dialog->spin_oversampling)); + dialog->conf->dft_number= gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(dialog->spin_dft_number)); + dialog->conf->dft_size = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(dialog->spin_dft_size)); + dialog->conf->peak_number + = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(dialog->spin_peak_number)); + dialog->conf->peak_order= gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(dialog->spin_peak_order)); + dialog->conf->peak_rejection_relation_db + = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(dialog->spin_peak_rejection_relation)); + dialog->conf->fft_size = atoi(gtk_combo_box_get_active_text(GTK_COMBO_BOX(dialog->combo_fft_size))); + dialog->conf->sample_rate + = atoi(gtk_combo_box_get_active_text(GTK_COMBO_BOX(dialog->combo_sample_rate))); + + int result = lingot_config_update_internal_params(dialog->conf); + + lingot_mainframe_change_config(dialog->mainframe, dialog->conf); + + if (!result) + { + message_dialog + = gtk_message_dialog_new( + GTK_WINDOW(dialog->win), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, + _("Temporal buffer is smaller than FFT size. It has been increased to %0.3f seconds"), dialog->conf->temporal_window); + gtk_dialog_run(GTK_DIALOG(message_dialog)); + gtk_widget_destroy (message_dialog); + } + } + +void lingot_config_dialog_close(LingotConfigDialog* dialog) + { + gtk_widget_destroy(dialog->win); + } diff --git a/src/lingot-config-dialog.h b/src/lingot-config-dialog.h new file mode 100644 index 0000000..208e020 --- /dev/null +++ b/src/lingot-config-dialog.h @@ -0,0 +1,74 @@ +//-*- C++ -*- +/* + * lingot, a musical instrument tuner. + * + * Copyright (C) 2004-2007 Ibán Cereijo Graña, Jairo Chapela Martínez. + * + * This file is part of lingot. + * + * lingot 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. + * + * lingot 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 lingot; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LINGOT_CONFIG_DIALOG_H__ +#define __LINGOT_CONFIG_DIALOG_H__ + +#include <gtk/gtk.h> + +#include "lingot-config.h" + +typedef struct _LingotConfigDialog LingotConfigDialog; + +struct _LingotConfigDialog + { + + // widgets that contains configuration information. + GtkWidget* spin_calculation_rate; + GtkWidget* spin_visualization_rate; + GtkWidget* spin_oversampling; + GtkWidget* spin_root_frequency_error; + GtkWidget* spin_temporal_window; + GtkWidget* spin_noise_threshold; + GtkWidget* spin_dft_number; + GtkWidget* spin_dft_size; + GtkWidget* spin_peak_number; + GtkWidget* spin_peak_order; + GtkWidget* spin_peak_rejection_relation; + GtkWidget* combo_fft_size; + GtkWidget* combo_sample_rate; + + GtkWidget* button_ok; + GtkWidget* button_cancel; + GtkWidget* button_apply; + GtkWidget* button_default; + + GtkWidget* label_sample_rate; + GtkWidget* label_root_frequency; + + LingotConfig* conf; // provisional configuration. + LingotConfig* conf_old; // restoration point for cancel. + + LingotMainFrame* mainframe; + + GtkWidget* win; // window + }; + +LingotConfigDialog* lingot_config_dialog_new(LingotMainFrame*); +void lingot_config_dialog_destroy(LingotConfigDialog*); + +void lingot_config_dialog_rewrite(LingotConfigDialog*); +void lingot_config_dialog_apply(LingotConfigDialog*); +void lingot_config_dialog_close(LingotConfigDialog*); + +#endif // __LINGOT_CONFIG_DIALOG_H__ diff --git a/src/lingot-config.c b/src/lingot-config.c new file mode 100644 index 0000000..c03a717 --- /dev/null +++ b/src/lingot-config.c @@ -0,0 +1,261 @@ +//-*- C++ -*- +/* + * lingot, a musical instrument tuner. + * + * Copyright (C) 2004-2007 Ibán Cereijo Graña, Jairo Chapela Martínez. + * + * This file is part of lingot. + * + * lingot 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. + * + * lingot 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 lingot; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <math.h> + +#include "lingot-config.h" +#include "lingot-mainframe.h" + +// the following tokens will appear in the config file. +char* token[] = + { "AUDIO_DEV", "SAMPLE_RATE", "OVERSAMPLING", "ROOT_FREQUENCY_ERROR", + "MIN_FREQUENCY", "FFT_SIZE", "TEMPORAL_WINDOW", "NOISE_THRESHOLD", + "CALCULATION_RATE", "VISUALIZATION_RATE", "PEAK_NUMBER", "PEAK_ORDER", + "PEAK_REJECTION_RELATION", "DFT_NUMBER", "DFT_SIZE", NULL // NULL terminated array + }; + +// print/scan param formats. +const char* format = "sddffdffffddfdd"; + +//---------------------------------------------------------------------------- + +LingotConfig* lingot_config_new() + { + + LingotConfig* config = malloc(sizeof(LingotConfig)); + + lingot_config_reset(config); // set default values. + + // internal parameters mapped to each token in the config file. + void* c_param[] = + { &config->audio_dev, &config->sample_rate, &config->oversampling, + &config->root_frequency_error, &config->min_frequency, + &config->fft_size, &config->temporal_window, + &config->noise_threshold_db, &config->calculation_rate, + &config->visualization_rate, &config->peak_number, + &config->peak_order, &config->peak_rejection_relation_db, + &config->dft_number, &config->dft_size }; + + memcpy(config->param, c_param, 15*sizeof(void*)); + + return config; + } + +void lingot_config_destroy(LingotConfig* config) + { + free(config); + } + +//---------------------------------------------------------------------------- +void lingot_config_reset(LingotConfig* config) + { + sprintf(config->audio_dev, "%s", "/dev/dsp"); + + config->sample_rate = 8000; // Hz + config->oversampling = 5; + config->root_frequency_error = 0; // Hz + config->min_frequency = 15; // Hz + config->fft_size = 512; // samples + config->temporal_window = 0.32; // seconds + config->calculation_rate = 20; // Hz + config->visualization_rate = 30; // Hz + config->noise_threshold_db = 20.0; // dB + + config->peak_number = 3; // peaks + config->peak_order = 1; // samples + config->peak_rejection_relation_db = 20; // dB + + config->dft_number = 2; // DFTs + config->dft_size = 15; // samples + + config->max_nr_iter = 10; // iterations + + //-------------------------------------------------------------------------- + + config->vr = -0.45; // near to minimum + + lingot_config_update_internal_params(config); + } + +//---------------------------------------------------------------------------- + +int lingot_config_update_internal_params(LingotConfig* config) + { + int result = 1; + + // derived parameters. + config->root_frequency = 440.0 + *pow(2.0, config->root_frequency_error/1200.0); + config->temporal_buffer_size = (unsigned int)ceil(config->temporal_window + *config->sample_rate/config->oversampling); + config->read_buffer_size = (unsigned int)ceil(config->sample_rate + /(config->calculation_rate*config->oversampling)); + config->peak_rejection_relation_nu = pow(10.0, + config->peak_rejection_relation_db/10.0); + config->noise_threshold_nu = pow(10.0, config->noise_threshold_db/10.0); + + if (config->temporal_buffer_size < config->fft_size) + { + config->temporal_window = ((double) config->fft_size + *config->oversampling)/config->sample_rate; + config->temporal_buffer_size = config->fft_size; + result = 0; + } + + return result; + } + +//---------------------------------------------------------------------------- + +void lingot_config_save(LingotConfig* config, char* filename) + { + unsigned int i; + FILE* fp; + + if ((fp = fopen(filename, "w")) == NULL) + { + char buff[100]; + sprintf(buff, "error saving config file %s ", filename); + perror(buff); + return; + } + + fprintf(fp, "# Config file automatically created by lingot\n\n"); + + for (i = 0; token[i]; i++) + switch (format[i]) + { + case 's': + fprintf(fp, "%s = %s\n", token[i], (char*) config->param[i]); + break; + case 'd': + fprintf(fp, "%s = %d\n", token[i], + *((unsigned int*) config->param[i])); + break; + case 'f': + fprintf(fp, "%s = %0.3f\n", token[i], *((FLT*) config->param[i])); + break; + } + + fclose(fp); + } + +//---------------------------------------------------------------------------- + +void lingot_config_load(LingotConfig* config, char* filename) + { + FILE* fp; + float aux; + int line; + int token_index; + char* char_buffer_pointer; + + const static char* delim = " \t=\n"; + +# define MAX_LINE_SIZE 100 + + char char_buffer[MAX_LINE_SIZE]; + + if ((fp = fopen(filename, "r")) == NULL) + { + sprintf(char_buffer, + "error opening config file %s, assuming default values ", filename); + perror(char_buffer); + return; + } + + line = 0; + + for (;;) + { + + line++; + + if (!fgets(char_buffer, MAX_LINE_SIZE, fp)) + break;; + + // printf("line %d: %s\n", line, s1); + + if (char_buffer[0] == '#') + continue; + + // tokens into the line. + char_buffer_pointer = strtok(char_buffer, delim); + + if (!char_buffer_pointer) + continue; // blank line. + + for (token_index = 0; token[token_index]; token_index++) + { + if (!strcmp(char_buffer_pointer, token[token_index])) + { + break; // found token. + } + } + + if (!token[token_index]) + { + fprintf(stderr, + "warning: parse error at line %i: unknown keyword %s\n", + line, char_buffer_pointer); + continue; + } + + // take the attribute value. + char_buffer_pointer = strtok(NULL, delim); + + if (!char_buffer_pointer) + { + fprintf(stderr, "warning: parse error at line %i: value expected\n", + line); + continue; + } + + // asign the value to the parameter. + switch (format[token_index]) + { + case 's': + sprintf(((char*) config->param[token_index]), "%s", + char_buffer_pointer); + break; + case 'd': + sscanf(char_buffer_pointer, "%d", + (unsigned int*) config->param[token_index]); + break; + case 'f': + sscanf(char_buffer_pointer, "%f", &aux); + *((FLT*) config->param[token_index]) = aux; + break; + } + + } + + fclose(fp); + + lingot_config_update_internal_params(config); + +# undef MAX_LINE_SIZE + } diff --git a/src/lingot-config.h b/src/lingot-config.h new file mode 100644 index 0000000..174730d --- /dev/null +++ b/src/lingot-config.h @@ -0,0 +1,109 @@ +//-*- C++ -*- +/* + * lingot, a musical instrument tuner. + * + * Copyright (C) 2004-2007 Ibán Cereijo Graña, Jairo Chapela Martínez. + * + * This file is part of lingot. + * + * lingot 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. + * + * lingot 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 lingot; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LINGOT_CONFIG_H__ +#define __LINGOT_CONFIG_H__ + +#include "lingot-defs.h" + +/* + Configuration class. Determines the tuner's behaviour. + Some parameters are internal only. + */ + +typedef struct _LingotConfig LingotConfig; + +struct _LingotConfig + { + void* param[15]; // parameter pointer array. + + char audio_dev[80]; // default "/dev/dsp" + unsigned int sample_rate; // soundcard sample rate. + unsigned int oversampling; // oversampling factor. + + // frequency of the root A note (internal parameter). + FLT root_frequency; + + FLT root_frequency_error; // deviation of the above root frequency. + + FLT min_frequency; // minimum valid frequency. + + unsigned int fft_size; // number of samples of the FFT. + + FLT calculation_rate; + FLT visualization_rate; + + FLT temporal_window; // duration in seconds of the temporal window. + + // samples stored in the temporal window (internal parameter). + unsigned int temporal_buffer_size; + + // samples read from soundcard. (internal parameter) + unsigned int read_buffer_size; + + FLT noise_threshold_db; // dB + FLT noise_threshold_nu; // natural units (internal parameter) + + // frequency finding algorithm configuration + //------------------------------------------- + + unsigned int peak_number; // number of maximum peaks considered. + + // number of adyacent samples needed to consider a peak. + unsigned int peak_order; + + /* maximum amplitude relation between principal and secondary peaks. + The max peak doesn't has to be the fundamental frequency carrier if it + has an amplitude relation with the fundamental considered peak lower than + this parameter. */ + FLT peak_rejection_relation_db; // dBs + FLT peak_rejection_relation_nu; // natural units (internal) + + // DFT approximation + unsigned int dft_number; // number of DFTs. + unsigned int dft_size; // samples of each DFT. + + // max iterations for Newton-Raphson algorithm. + unsigned int max_nr_iter; + + //---------------------------------------------------------------------------- + + // gauge rest value. (gauge contemplates [-0.5, 0.5]) + FLT vr; + + //---------------------------------------------------------------------------- + }; + +LingotConfig* lingot_config_new(); +void lingot_config_destroy(LingotConfig*); + +// back to default configuration. +void lingot_config_reset(LingotConfig*); + +// derivate internal parameters from external ones. +int lingot_config_update_internal_params(LingotConfig*); + +void lingot_config_save(LingotConfig*, char* filename); +void lingot_config_load(LingotConfig*, char* filename); + +#endif // __LINGOT_CONFIG_H__ diff --git a/src/lingot-core.c b/src/lingot-core.c new file mode 100644 index 0000000..d0cdaec --- /dev/null +++ b/src/lingot-core.c @@ -0,0 +1,416 @@ +//-*- C++ -*- +/* + * lingot, a musical instrument tuner. + * + * Copyright (C) 2004-2007 Ibán Cereijo Graña, Jairo Chapela Martínez. + * + * This file is part of lingot. + * + * lingot 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. + * + * lingot 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 lingot; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdio.h> +#include <math.h> +#include <sys/soundcard.h> +#include <string.h> +#include <errno.h> + +#ifndef LIB_FFTW +# include "lingot-complex.h" +#endif + +#include "lingot-fft.h" +#include "lingot-signal.h" +#include "lingot-core.h" +#include "lingot-config.h" + +LingotCore* lingot_core_new(LingotConfig* conf) { + + LingotCore* core = malloc(sizeof(LingotCore)); + + core->conf = conf; + core->running = 1; + +# ifdef LIBSNDOBJ +# ifdef OSS + core->audio = new SndRTIO(1, SND_INPUT, 512, 512, SHORTSAM_LE, NULL, + core->conf->read_buffer_size*core->conf->oversampling, core->conf->sample_rate, core->conf->audio_dev); +# endif +# ifdef ALSA + core->audio = new SndRTIO(1, SND_INPUT, 512, 4, SHORTSAM_LE, NULL, + core->conf->read_buffer_size*core->conf->oversampling, core->conf->sample_rate, "plughw:0,0"); +# endif +# else + // creates an audio handler. + core->audio = lingot_audio_new(1, core->conf->sample_rate, SAMPLE_FORMAT, + core->conf->audio_dev); +# endif + + // since the SPD is simmetrical, we only store the 1st half. + if (core->conf->fft_size > 256) { + core->spd_fft = malloc((core->conf->fft_size >> 1)*sizeof(FLT)); + core->X = malloc((core->conf->fft_size >> 1)*sizeof(FLT)); + memset(core->spd_fft, 0, (core->conf->fft_size >> 1)*sizeof(FLT)); + memset(core->X, 0, (core->conf->fft_size >> 1)*sizeof(FLT)); + } else { // if the fft size is 256, we store the whole signal for representation. + core->spd_fft = malloc((core->conf->fft_size)*sizeof(FLT)); + core->X = malloc((core->conf->fft_size)*sizeof(FLT)); + memset(core->spd_fft, 0, core->conf->fft_size*sizeof(FLT)); + memset(core->X, 0, (core->conf->fft_size)*sizeof(FLT)); + } + + core->spd_dft = malloc((core->conf->dft_size)*sizeof(FLT)); + memset(core->spd_dft, 0, core->conf->dft_size*sizeof(FLT)); + + core->diff2_spd_fft = malloc(core->conf->fft_size*sizeof(FLT)); // 2nd derivative from SPD. + memset(core->diff2_spd_fft, 0, core->conf->fft_size*sizeof(FLT)); + + memset(core->spd_dft, 0, core->conf->dft_size*sizeof(FLT)); + +#ifndef LIB_FFTW + lingot_fft_create_phase_factors(conf); // creates the phase factors for FFT. + core->fft_out = malloc((core->conf->fft_size)*sizeof(LingotComplex)); // complex signal in freq domain. + memset(core->fft_out, 0, core->conf->fft_size*sizeof(LingotComplex)); +#else + core->fftw_in = new fftw_complex[core->conf->fft_size]; + memset(core->fftw_in, 0, core->conf->fft_size*sizeof(fftw_complex)); + core->fftw_out = new fftw_complex[core->conf->fft_size]; + memset(core->fftw_out, 0, core->conf->fft_size*sizeof(fftw_complex)); + core->fftwplan = fftw_create_plan(core->conf->fft_size, FFTW_FORWARD, FFTW_ESTIMATE); +#endif + + // read buffer from soundcard. + core->read_buffer= malloc((core->conf->read_buffer_size + *core->conf->oversampling)*sizeof(SAMPLE_TYPE)); + memset(core->read_buffer, 0, (core->conf->read_buffer_size + *core->conf->oversampling)*sizeof(SAMPLE_TYPE)); + + // read buffer from soundcard in floating point format. + core->flt_read_buffer= malloc((core->conf->read_buffer_size + *core->conf->oversampling)*sizeof(FLT)); + memset(core->flt_read_buffer, 0, (core->conf->read_buffer_size + *core->conf->oversampling)*sizeof(FLT)); + + // stored samples. + core->temporal_buffer = malloc((core->conf->temporal_buffer_size) + *sizeof(FLT)); + memset(core->temporal_buffer, 0, core->conf->temporal_buffer_size + *sizeof(FLT)); + + core->hamming_window_temporal = malloc((core->conf->temporal_buffer_size) + *sizeof(FLT)); + lingot_signal_hamming_window(core->conf->temporal_buffer_size, + core->hamming_window_temporal); + core->hamming_window_fft = malloc((core->conf->fft_size) *sizeof(FLT)); + lingot_signal_hamming_window(core->conf->fft_size, core->hamming_window_fft); + + core->windowed_temporal_buffer = malloc((core->conf->temporal_buffer_size) + *sizeof(FLT)); + memset(core->windowed_temporal_buffer, 0, core->conf->temporal_buffer_size + *sizeof(FLT)); + core->windowed_fft_buffer = malloc((core->conf->fft_size) *sizeof(FLT)); + memset(core->windowed_fft_buffer, 0, core->conf->fft_size *sizeof(FLT)); + + /* + * 8 order Chebyshev filters, with wc=0.9/i (normalized respect to + * Pi). We take 0.9 instead of 1 to leave a 10% of safety margin, + * in order to avoid aliased frequencies near to w=Pi, due to non + * ideality of the filter. + * + * The cut frequencies wc=Pi/i, with i=1..20, correspond with the + * oversampling factor, avoiding aliasing at decimation. + * + * Why Chebyshev filters?, for a given order, those filters yield + * abrupt falls than other ones as Butterworth, making the most of + * the order. Although Chebyshev filters affects more to the phase, + * it doesn't matter due to the analysis is made on the signal + * power distribution (only module). + */ + core->antialiasing_filter= lingot_filter_cheby_design(8, 0.5, 0.9 + /core->conf->oversampling); + + // ------------------------------------------------------------ + + core->freq = 0.0; + return core; +} + +// ----------------------------------------------------------------------- + +/* Deallocate resources */ +void lingot_core_destroy(LingotCore* core) { + pthread_attr_destroy(&core->attr); + +#ifdef LIB_FFTW + fftw_destroy_plan(core->fftwplan); + free(core->fftw_in); + free(core->fftw_out); +#else + lingot_fft_destroy_phase_factors(); // destroy phase factors. + free(core->fft_out); +#endif + + lingot_audio_destroy(core->audio); + + free(core->spd_fft); + free(core->X); + free(core->spd_dft); + free(core->diff2_spd_fft); + free(core->read_buffer); + free(core->flt_read_buffer); + free(core->temporal_buffer); + + free(core->windowed_temporal_buffer); + free(core->windowed_fft_buffer); + + free(core->hamming_window_temporal); + free(core->hamming_window_fft); + + lingot_filter_destroy(core->antialiasing_filter); + + free(core); +} + +// ----------------------------------------------------------------------- + +// signal decimation with antialiasing, in & out overlapables. +void lingot_core_decimate(LingotCore* core, FLT* in, FLT* out) { + register unsigned int i, j; + + // low pass filter to avoid aliasing. + lingot_filter_filter(core->antialiasing_filter, + core->conf->read_buffer_size*core->conf->oversampling, in, in); + + // compression. + for (i = j = 0; i < core->conf->read_buffer_size; i++, j + += core->conf->oversampling) + out[i] = in[j]; +} + +// ----------------------------------------------------------------------- + +void lingot_core_process(LingotCore* core) { + register unsigned int i, k; // loop variables. + FLT delta_w_FFT = 2.0*M_PI/core->conf->fft_size; + // FFT resolution in rads. + +# ifdef LIBSNDOBJ + audio->Read(); + for (i = 0; i < core->conf->oversampling*core->conf->read_buffer_size; i++) + flt_read_buffer[i] = audio->Output(i); +# else + if ((lingot_audio_read(core->audio, core->read_buffer, + core->conf->oversampling*core->conf->read_buffer_size + *sizeof(SAMPLE_TYPE)))< 0) { + //perror("Error reading samples"); + return; + } + + for (i = 0; i < core->conf->oversampling*core->conf->read_buffer_size; i++) + core->flt_read_buffer[i] = core->read_buffer[i]; +# endif + + // + // just readed: + // + // ---------------------------- + // |bxxxbxxxbxxxbxxxbxxxbxxxbxxx| + // ---------------------------- + // + // <----------------------------> read_buffer_size*oversampling + // + + /* we shift the temporal window to leave a hollow where place the new piece + of data read. The buffer is actually a queue. */ + if (core->conf->temporal_buffer_size > core->conf->read_buffer_size) + memcpy(core->temporal_buffer, + &core->temporal_buffer[core->conf->read_buffer_size], + (core->conf->temporal_buffer_size + - core->conf->read_buffer_size) *sizeof(FLT)); + + // + // previous buffer situation: + // + // ------------------------------------------ + // | xxxxxxxxxxxxxxxxxxxxxx | yyyyy | aaaaaaa | + // ------------------------------------------ + // <------> read_buffer_size + // <---------------> fft_size + // <----------------------------------------> temporal_buffer_size + // + // new situation: + // + // ------------------------------------------ + // | xxxxxxxxxxxxxxxxyyyyaa | aaaaa | | + // ------------------------------------------ + // + + /* we decimate the read signal and put it at the end of the buffer. */ + if (core->conf->oversampling > 1) + lingot_core_decimate( + core, + core->flt_read_buffer, + &core->temporal_buffer[core->conf->temporal_buffer_size - core->conf->read_buffer_size]); + else + memcpy( + &core->temporal_buffer[core->conf->temporal_buffer_size - core->conf->read_buffer_size], + core->flt_read_buffer, core->conf->read_buffer_size*sizeof(FLT)); + // + // ------------------------------------------ + // | xxxxxxxxxxxxxxxxyyyyaa | aaaaa | bbbbbbb | + // ------------------------------------------ + // + + // ----------------- TRANSFORMATION TO FREQUENCY DOMAIN ---------------- + + FLT _1_N2 = 1.0/(core->conf->fft_size*core->conf->fft_size); + // SPD normalization constant + + // windowing + for (i = 0; i < core->conf->fft_size; i++) { + core->windowed_fft_buffer[i] + = core->temporal_buffer[core->conf->temporal_buffer_size - core->conf->fft_size + i] + *core->hamming_window_fft[i]; + } + +# ifdef LIB_FFTW + for (i = 0; i < core->conf->fft_size; i++) + fftw_in[i].re = core->windowed_fft_buffer[i]; + + // transformation. + fftw_one(core->fftwplan, core->fftw_in, core->fftw_out); + + // esteem of SPD from FFT. (normalized squared module) + for (i = 0; i < ((core->conf->fft_size > 256) ? (core->conf->fft_size >> 1) : 256); i++) + core->spd_fft[i] = (core->fftw_out[i].re*core->fftw_out[i].re + + core->fftw_out[i].im*core->fftw_out[i].im)*_1_N2; +# else + + // transformation. + lingot_fft_fft(core->windowed_fft_buffer, core->fft_out, + core->conf->fft_size); + + // esteem of SPD from FFT. (normalized squared module) + for (i = 0; i < ((core->conf->fft_size > 256) ? (core->conf->fft_size >> 1) + : 256); i++) + core->spd_fft[i] = (core->fft_out[i].r*core->fft_out[i].r + + core->fft_out[i].i*core->fft_out[i].i)*_1_N2; +# endif + + // representable piece + memcpy(core->X, core->spd_fft, + ((core->conf->fft_size > 256) ? (core->conf->fft_size >> 1) : 256) + *sizeof(FLT)); + + // truncated 2nd derivative esteem, to enhance peaks + core->diff2_spd_fft[0] = 0.0; + for (i = 1; i < (core->conf->fft_size >> 1) - 1; i++) { + core->diff2_spd_fft[i] = 2.0*core->spd_fft[i]- core->spd_fft[i - 1] + - core->spd_fft[i + 1]; // centred 2nd order derivative, to avoid group delay. + if (core->diff2_spd_fft[i] < 0.0) + core->diff2_spd_fft[i] = 0.0; // truncation + } + + // peaks searching in that signal. + int Mi = lingot_signal_get_fundamental_peak(core->conf, core->spd_fft, + core->diff2_spd_fft, (core->conf->fft_size >> 1)); // take the fundamental peak. + + if (Mi == (signed) (core->conf->fft_size >> 1)) { + core->freq = 0.0; + return; + } + + FLT w = (Mi - 1)*delta_w_FFT; + // frecuencia de la muestra anterior al pico. + + // Approximation to fundamental frequency by selective DFTs + // --------------------------------------------------------- + + FLT d_w = delta_w_FFT; + for (k = 0; k < core->conf->dft_number; k++) { + + d_w = 2.0*d_w/(core->conf->dft_size - 1); // resolution in rads. + + if (k == 0) { + lingot_fft_spd(core->windowed_fft_buffer, core->conf->fft_size, w + + d_w, d_w, &core->spd_dft[1], core->conf->dft_size- 2); + core->spd_dft[0] = core->spd_fft[Mi - 1]; + core->spd_dft[core->conf->dft_size - 1] = core->spd_fft[Mi + 1]; // 2 samples known. + } else + lingot_fft_spd(core->windowed_fft_buffer, core->conf->fft_size, w, + d_w, core->spd_dft, core->conf->dft_size); + + lingot_signal_get_max(core->spd_dft, core->conf->dft_size, &Mi); // search the maximum. + + w += (Mi - 1)*d_w; // previous sample to the peak. + } + + w += d_w; // approximation by DFTs. + + // windowing + for (i = 0; i < core->conf->temporal_buffer_size; i++) { + core->windowed_temporal_buffer[i] = core->temporal_buffer[i] + *core->hamming_window_temporal[i]; + } + + // Maximum finding by Newton-Raphson + // ----------------------------------- + + FLT wk = -1.0e5; + FLT wkm1 = w; + // first iterator set to the current approximation. + FLT d1_SPD, d2_SPD; + + for (k = 0; (k < core->conf->max_nr_iter) && (fabs(wk - wkm1) > 1.0e-8); k++) { + wk = wkm1; + + // ! we use the WHOLE temporal window for greater precission. + lingot_fft_spd_diffs(core->windowed_temporal_buffer, + core->conf->temporal_buffer_size, wk, &d1_SPD, &d2_SPD); + //printf("%f %f %f\n", wk, d1_SPD, d2_SPD); + wkm1 = wk - d1_SPD/d2_SPD; + } + + w = wkm1; // frequency in rads. + core->freq = (w*core->conf->sample_rate) /(2.0*M_PI + *core->conf->oversampling); // analog frequency. + +} + +/* start running the core in another thread */ +void lingot_core_start(LingotCore* core) { + pthread_attr_init(&core->attr); + + // detached thread. + // pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_create(&core->thread, &core->attr, (void* (*)(void*)) lingot_core_run, core); +} + +/* stop running the core */ +void lingot_core_stop(LingotCore* core) { + void* thread_result; + + core->running = 0; + + // wait for the thread exit + pthread_join(core->thread, &thread_result); +} + +/* run the core */ +void lingot_core_run(LingotCore* core) { + while (core->running) { + lingot_core_process(core); // process new data block. + } +} diff --git a/src/lingot-core.h b/src/lingot-core.h new file mode 100644 index 0000000..1d58b9a --- /dev/null +++ b/src/lingot-core.h @@ -0,0 +1,109 @@ +//-*- C++ -*- +/* + * lingot, a musical instrument tuner. + * + * Copyright (C) 2004-2007 Ibán Cereijo Graña, Jairo Chapela Martínez. + * + * This file is part of lingot. + * + * lingot 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. + * + * lingot 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 lingot; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LINGOT_CORE_H__ +#define __LINGOT_CORE_H__ + +#include <pthread.h> + +#include "lingot-defs.h" +#include "lingot-complex.h" +#include "lingot-filter.h" +#include "lingot-config.h" + +#ifdef LIB_FFTW +# include <fftw.h> +#endif + +#ifdef LIBSNDOBJ +# include <SndObj/AudioDefs.h> +#else +# include "lingot-audio.h" +#endif + +typedef struct _LingotCore LingotCore; + +struct _LingotCore { + + // -- shared data -- + FLT freq; // analog frequency calculated. + FLT* X; // visual portion of FFT. + // -- shared data -- + +# ifdef LIBSNDOBJ + SndRTIO* audio; // audio handler. +# else + LingotAudio* audio; // audio handler. +# endif + + SAMPLE_TYPE* read_buffer; + FLT* flt_read_buffer; + FLT* temporal_buffer; // sample memory. + + // precomputed hamming windows + FLT* hamming_window_temporal; + FLT* hamming_window_fft; + + // windowed signals + FLT* windowed_temporal_buffer; + FLT* windowed_fft_buffer; + + // spectral power distribution esteem. + FLT* spd_fft; + FLT* spd_dft; + FLT* diff2_spd_fft; + +# ifdef LIB_FFTW + fftw_complex* fftw_in; + fftw_complex* fftw_out; // complex signals in time and freq. + fftw_plan fftwplan; +# else + LingotComplex* fft_out; // complex signal in freq. +# endif + + LingotFilter* antialiasing_filter; // antialiasing filter for decimation. + + int running; + + LingotConfig* conf; // configuration structure + + // pthread-related member variables + pthread_t thread; + pthread_attr_t attr; +}; + +//---------------------------------------------------------------- + +LingotCore* lingot_core_new(LingotConfig*); +void lingot_core_destroy(LingotCore*); + +// start process +void lingot_core_start(LingotCore*); + +// stop process +void lingot_core_stop(LingotCore*); + +// process thread +void lingot_core_run(LingotCore*); + +#endif //__LINGOT_CORE_H__ diff --git a/src/lingot-defs.h b/src/lingot-defs.h new file mode 100644 index 0000000..09625fa --- /dev/null +++ b/src/lingot-defs.h @@ -0,0 +1,52 @@ +//-*- C++ -*- +/* + * lingot, a musical instrument tuner. + * + * Copyright (C) 2004-2007 Ibán Cereijo Graña, Jairo Chapela Martínez. + * + * This file is part of lingot. + * + * lingot 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. + * + * lingot 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 lingot; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LINGOT_DEFS_H__ +#define __LINGOT_DEFS_H__ + +#include <sys/types.h> +#include "../config.h" + +// floating point precission. +#define FLT double + +#define SAMPLE_TYPE int16_t +#define SAMPLE_FORMAT AFMT_S16_LE + +#define CONFIG_DIR_NAME ".lingot/" +#define DEFAULT_CONFIG_FILE_NAME "lingot.conf" +extern char CONFIG_FILE_NAME[]; + +#define QUICK_MESSAGES + +#define GTK_EVENTS_RATE 20.0 +#define GAUGE_RATE 60.0 + +/* object forward declaration */ +typedef struct _LingotMainFrame LingotMainFrame; + +// optionally we can use the following libraries +//#define LIB_FFTW +//#define LIBSNDOBJ + +#endif diff --git a/src/lingot-fft.c b/src/lingot-fft.c new file mode 100644 index 0000000..18de134 --- /dev/null +++ b/src/lingot-fft.c @@ -0,0 +1,177 @@ +//-*- C++ -*-
+/*
+ * lingot, a musical instrument tuner.
+ *
+ * Copyright (C) 2004-2007 Ibán Cereijo Graña, Jairo Chapela Martínez.
+ *
+ * This file is part of lingot.
+ *
+ * lingot 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.
+ *
+ * lingot 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 lingot; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <math.h>
+#include <stdlib.h>
+
+#include "lingot-fft.h"
+#include "lingot-config.h"
+
+/*
+ DFT functions.
+ */
+
+#ifndef LIB_FFTW
+
+#include "lingot-complex.h"
+
+// phase factor table, for FFT optimization.
+LingotComplex* wn;
+
+// creates the phase factor table.
+void lingot_fft_create_phase_factors(LingotConfig* conf)
+ {
+ FLT alpha;
+ unsigned int i;
+
+ wn = (LingotComplex*) malloc((conf->fft_size >> 1)*sizeof(LingotComplex));
+
+ for (i = 0; i < (conf->fft_size >> 1); i++)
+ {
+ alpha = -2.0*i*M_PI/conf->fft_size;
+ wn[i].r = cos(alpha);
+ wn[i].i = sin(alpha);
+ }
+ }
+
+void lingot_fft_destroy_phase_factors()
+ {
+ free(wn);
+ }
+
+//------------------------------------------------------------------------
+
+// Fast Fourier Transform.
+void _lingot_fft_fft(FLT* in, LingotComplex* out, unsigned long int N,
+ unsigned long int offset, unsigned long int d1, unsigned long int step)
+ {
+ LingotComplex X1, X2;
+ unsigned long int Np2 = (N >> 1); // N/2
+ register unsigned long int a, b, c, q;
+
+ if (N == 2)
+ { // butterfly for N = 2;
+
+ X1.r = in[offset];
+ X1.i = 0.0;
+ X2.r = in[offset + step];
+ X2.i = 0.0;
+
+ lingot_complex_add(&X1, &X2, &out[d1]);
+ lingot_complex_sub(&X1, &X2, &out[d1 + Np2]);
+
+ return;
+ }
+
+ _lingot_fft_fft(in, out, Np2, offset, d1, step << 1);
+ _lingot_fft_fft(in, out, Np2, offset + step, d1 + Np2, step << 1);
+
+ for (q = 0, c = 0; q < (N >> 1); q++, c += step)
+ {
+
+ a = q + d1;
+ b = a + Np2;
+
+ X1 = out[a];
+ lingot_complex_mul(&out[b], &wn[c], &X2);
+ lingot_complex_add(&X1, &X2, &out[a]);
+ lingot_complex_sub(&X1, &X2, &out[b]);
+ }
+ }
+
+void lingot_fft_fft(FLT* in, LingotComplex* out, unsigned long int N)
+ {
+ _lingot_fft_fft(in, out, N, 0, 0, 1);
+ }
+
+#endif
+
+//------------------------------------------------------------------------
+
+
+/* Spectral Power Distribution esteem, selectively in frequency, by DFT.
+ transforms signal in of N1 samples from frequency wi, with sample
+ separation of dw rads, storing the result on buffer out with N2 samples. */
+void lingot_fft_spd(FLT* in, int N1, FLT wi, FLT dw, FLT* out, int N2)
+ {
+ FLT Xr, Xi;
+ FLT wn;
+ FLT N1_2 = N1*N1;
+ register int i, n;
+
+ for (i = 0; i < N2; i++)
+ {
+
+ Xr = 0.0;
+ Xi = 0.0;
+
+ for (n = 0; n < N1; n++)
+ { // O(n1*n2) :(
+
+ wn = (wi + dw*i)*n;
+ Xr = Xr + cos(wn)*in[n];
+ Xi = Xi - sin(wn)*in[n];
+ }
+
+ out[i] = (Xr*Xr + Xi*Xi)/N1_2; // normalized squared module.
+ }
+ }
+
+//------------------------------------------------------------------------
+
+/*
+ Evaluates 1st and 2nd derivatives from SPD at frequency w.
+ */
+void lingot_fft_spd_diffs(FLT* in, int N, FLT w, FLT* out_d1, FLT* out_d2)
+ {
+ FLT x_cos_wn;
+ FLT x_sin_wn;
+ register int n;
+
+ FLT SUM_x_sin_wn = 0.0;
+ FLT SUM_x_cos_wn = 0.0;
+ FLT SUM_x_n_sin_wn = 0.0;
+ FLT SUM_x_n_cos_wn = 0.0;
+ FLT SUM_x_n2_sin_wn = 0.0;
+ FLT SUM_x_n2_cos_wn = 0.0;
+
+ for (n = 0; n < N; n++)
+ {
+
+ x_cos_wn = in[n]*cos(w*n);
+ x_sin_wn = in[n]*sin(w*n);
+
+ SUM_x_sin_wn += x_sin_wn;
+ SUM_x_cos_wn += x_cos_wn;
+ SUM_x_n_sin_wn += x_sin_wn*n;
+ SUM_x_n_cos_wn += x_cos_wn*n;
+ SUM_x_n2_sin_wn += x_sin_wn*n*n;
+ SUM_x_n2_cos_wn += x_cos_wn*n*n;
+ }
+
+ FLT N_2 = N*N;
+ *out_d1 = 2.0*(SUM_x_sin_wn*SUM_x_n_cos_wn - SUM_x_cos_wn*SUM_x_n_sin_wn)
+ /N_2;
+ *out_d2 = 2.0*(SUM_x_n_cos_wn*SUM_x_n_cos_wn - SUM_x_sin_wn*SUM_x_n2_sin_wn
+ +SUM_x_n_sin_wn*SUM_x_n_sin_wn - SUM_x_cos_wn*SUM_x_n2_cos_wn)/N_2;
+ }
diff --git a/src/lingot-fft.h b/src/lingot-fft.h new file mode 100644 index 0000000..b958416 --- /dev/null +++ b/src/lingot-fft.h @@ -0,0 +1,52 @@ +//-*- C++ -*-
+/*
+ * lingot, a musical instrument tuner.
+ *
+ * Copyright (C) 2004-2007 Ibán Cereijo Graña, Jairo Chapela Martínez.
+ *
+ * This file is part of lingot.
+ *
+ * lingot 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.
+ *
+ * lingot 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 lingot; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _LINGOT_FFT_H_
+#define _LINGOT_FFT_H_
+
+/*
+ Fourier transforms.
+ */
+
+#include "lingot-defs.h"
+
+#ifndef LIB_FFTW
+
+# include "lingot-complex.h"
+# include "lingot-config.h"
+
+void lingot_fft_create_phase_factors(LingotConfig* conf);
+void lingot_fft_destroy_phase_factors();
+
+// Fast Fourier Transform implementation.
+void lingot_fft_fft(FLT* in, LingotComplex* out, unsigned long int N);
+
+#endif // not LIB_FFTW
+
+// Spectral Power Distribution (SPD) esteem, selectively in frequency.
+void lingot_fft_spd(FLT* in, int N1, FLT wi, FLT dw, FLT* out, int N2);
+
+// first and second SPD derivatives at frequency w.
+void lingot_fft_spd_diffs(FLT* in, int N, FLT w, FLT* out_d1, FLT* out_d2);
+
+#endif
diff --git a/src/lingot-filter.c b/src/lingot-filter.c new file mode 100644 index 0000000..f3c5528 --- /dev/null +++ b/src/lingot-filter.c @@ -0,0 +1,258 @@ +//-*- C++ -*- +/* + * filter, a musical instrument tuner. + * + * Copyright (C) 2004-2007 Ibán Cereijo Graña, Jairo Chapela Martínez. + * + * This file is part of filter. + * + * filter 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. + * + * filter 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 filter; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <memory.h> +#include <math.h> + +#include "lingot-complex.h" +#include "lingot-filter.h" + +#define max(a,b) (((a)<(b))?(b):(a)) + +// given each polynomial order and coefs, with optional initial status. +LingotFilter* lingot_filter_new(unsigned int Na, unsigned int Nb, FLT* a, FLT* b) { + unsigned int i; + LingotFilter* filter = malloc(sizeof(LingotFilter)); + filter->N = max(Na, Nb); + + filter->a = malloc((filter->N + 1)*sizeof(FLT)); + filter->b = malloc((filter->N + 1)*sizeof(FLT)); + filter->s = malloc((filter->N + 1)*sizeof(FLT)); + + for (i = 0; i < filter->N + 1; i++) + filter->a[i] = filter->b[i] = filter->s[i] = 0.0; + + memcpy(filter->a, a, (Na + 1)*sizeof(FLT)); + memcpy(filter->b, b, (Nb + 1)*sizeof(FLT)); + + for (i = 0; i < filter->N + 1; i++) { + filter->a[i] /= a[0]; // polynomial normalization. + filter->b[i] /= a[0]; + } + + return filter; +} + +void lingot_filter_destroy(LingotFilter* filter) { + free(filter->a); + free(filter->b); + free(filter->s); + + free(filter); +} + +// Digital Filter Implementation II, in & out overlapables. +void lingot_filter_filter(LingotFilter* filter, unsigned int n, FLT* in, + FLT* out) { + FLT w, y; + register unsigned int i; + register int j; + + for (i = 0; i < n; i++) { + + w = in[i]; + y = 0.0; + + for (j = filter->N - 1; j >= 0; j--) { + w -= filter->a[j + 1]*filter->s[j]; + y += filter->b[j + 1]*filter->s[j]; + filter->s[j + 1] = filter->s[j]; + } + + y += w*filter->b[0]; + filter->s[0] = w; + + out[i] = y; + } +} + +// single sample filtering +FLT lingot_filter_filter_sample(LingotFilter* filter, FLT in) +{ + FLT result; + + lingot_filter_filter(filter, 1, &in, &result); + return result; +} + +// vector prod +void lingot_filter_vector_product(int n, LingotComplex* vector, + LingotComplex* result) { + register int i; + LingotComplex aux1; + + result->r = 1.0; + result->i = 0.0; + + for (i = 0; i < n; i++) { + aux1.r = -vector[i].r; + aux1.i = -vector[i].i; + lingot_complex_mul(result, &aux1, result); + } + +} + +// Chebyshev filters +LingotFilter* lingot_filter_cheby_design(unsigned int n, FLT Rp, FLT wc) { + int i; // loops + int k; + int p; + + FLT* a + = malloc((n + 1)*sizeof(FLT)); + FLT* b + = malloc((n + 1)*sizeof(FLT)); + + FLT* new_a + = malloc((n + 1)*sizeof(FLT)); + FLT* new_b + = malloc((n + 1)*sizeof(FLT)); + + // locate poles + LingotComplex* pole = malloc(n*sizeof(LingotComplex)); + + for (i = 0; i < n; i++) { + pole[i].r = 0.0; + pole[i].i = 0.0; + } + + FLT T = 2.0; + // 2Hz + FLT W = 2.0/T*tan(M_PI*wc/T); + + FLT epsilon = sqrt(pow(10.0, 0.1*Rp) - 1); + FLT v0 = asinh(1/epsilon)/n; + + FLT sv0 = sinh(v0); + FLT cv0 = cosh(v0); + + FLT t; + + for (i = -(n-1), k = 0; k < n; i+=2, k++) { + t = M_PI*i/(2.0*n); + pole[k].r = -sv0*cos(t); + pole[k].i = cv0*sin(t); + } + + LingotComplex gain; + + lingot_filter_vector_product(n, pole, &gain); + + if ((n&1)==0) {// even + FLT f = pow(10.0, -0.05*Rp); + gain.r *= f; + gain.i *= f; + } + + FLT f = pow(W, n); + gain.r *= f; + gain.i *= f; + + for (i = 0; i < n; i++) { + pole[i].r *= W; + pole[i].i *= W; + } + + // bilinear transform + LingotComplex* sp = malloc(n*sizeof(LingotComplex)); + + for (i = 0; i < n; i++) { + sp[i].r = (2.0 - pole[i].r*T)/T; + sp[i].i = (0.0 - pole[i].i*T)/T; + } + + LingotComplex tmp1; + LingotComplex aux2; + + lingot_filter_vector_product(n, sp, &tmp1); + + free(sp); + + lingot_complex_div(&gain, &tmp1, &gain); + + for (i = 0; i < n; i++) { + tmp1.r = (2.0 + pole[i].r*T); + tmp1.i = (0.0 + pole[i].i*T); + aux2.r = (2.0 - pole[i].r*T); + aux2.i = (0.0 - pole[i].i*T); + lingot_complex_div(&tmp1, &aux2, &pole[i]); + } + + // compute filter coefficients from pole/zero values + a[0] = 1.0; + b[0] = 1.0; + new_a[0] = 1.0; + new_b[0] = 1.0; + + for (i = 1; i <= n; i++) { + a[i] = 0.0; + b[i] = 0.0; + new_a[i] = 0.0; + new_b[i] = 0.0; + } + + if ((n & 1) == 1) // odd + { + // first subfilter is first order + a[1] = -pole[n/2].r; + b[1] = 1.0; + } + + // iterate over the conjugate pairs + for (p = 0; p < n/2; p++) { + FLT b1 = 2.0; + FLT b2 = 1.0; + + FLT a1 = -2.0*pole[p].r; + FLT a2 = pole[p].r*pole[p].r + pole[p].i*pole[p].i; + + // 2nd order subfilter per each pair + new_a[1] = a[1] + a1*a[0]; + new_b[1] = b[1] + b1*b[0]; + + // poly multiplication + for (i = 2; i <= n; i++) { + new_a[i] = a[i] + a1*a[i - 1]+ a2*a[i - 2]; + new_b[i] = b[i] + b1*b[i - 1]+ b2*b[i - 2]; + } + for (i = 1; i <= n; i++) { + a[i] = new_a[i]; + b[i] = new_b[i]; + } + } + + gain.r = fabs(gain.r); + for (i = 0; i <= n; i++) { + b[i] *= gain.r; + } + + LingotFilter* result = lingot_filter_new(n, n, a, b); + + free(a); + free(b); + free(new_a); + free(new_b); + free(pole); + + return result; +} diff --git a/src/lingot-filter.h b/src/lingot-filter.h new file mode 100644 index 0000000..b2ea389 --- /dev/null +++ b/src/lingot-filter.h @@ -0,0 +1,66 @@ +//-*- C++ -*- +/* + * lingot, a musical instrument tuner. + * + * Copyright (C) 2004-2007 Ibán Cereijo Graña, Jairo Chapela Martínez. + * + * This file is part of lingot. + * + * lingot 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. + * + * lingot 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 lingot; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LINGOT_FILTER_H__ +#define __LINGOT_FILTER_H__ + +#include <fcntl.h> +#include <stdlib.h> + +#include "lingot-defs.h" + +/* + digital filtering implementation. + */ + +typedef struct _LingotFilter LingotFilter; + +struct _LingotFilter + { + + FLT* a; + FLT* b; // coefs + FLT* s; // status + + unsigned int N; + + }; + +LingotFilter + * lingot_filter_new(unsigned int Na, unsigned int Nb, FLT* a, FLT* b); + +/** + * Design a Chebyshev type I low pass filter with Rp dB of pass band ripple + * with cutoff pi*wc radians. + */ +LingotFilter* lingot_filter_cheby_design(unsigned int order, FLT Rp, FLT wc); + +void lingot_filter_destroy(LingotFilter*); + +// Digital Filter Implementation II, in & out overlapables. Vector filtering +void lingot_filter_filter(LingotFilter*, unsigned int n, FLT* in, FLT* out); + +// sample filtering +FLT lingot_filter_filter_sample(LingotFilter*, FLT in); + +#endif diff --git a/src/lingot-gauge.c b/src/lingot-gauge.c new file mode 100644 index 0000000..d092ed1 --- /dev/null +++ b/src/lingot-gauge.c @@ -0,0 +1,92 @@ +//-*- C++ -*- +/* + * lingot, a musical instrument tuner. + * + * Copyright (C) 2004-2007 Ibán Cereijo Graña, Jairo Chapela Martínez. + * + * This file is part of lingot. + * + * lingot 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. + * + * lingot 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 lingot; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "lingot-gauge.h" + +LingotGauge* lingot_gauge_new(FLT initial_position) + { + + // + // ----- ERROR GAUGE FILTER CONFIGURATION ----- + // + // dynamic model of the gauge: + // + // 2 + // d d + // --- s(t) = k (e(t) - s(t)) - q -- s(t) + // 2 dt + // dt + // + // acceleration of gauge position 's(t)' linealy depends on the difference + // respect to the input stimulus 'e(t)' (destination position). Inserting + // a friction coefficient 'q', acceleration proportionaly diminish with + // velocity (typical friction in mechanics). 'k' is the adaptation constant, + // and depends on the gauge mass. + // + // with the following derivatives approximation (valid for high sample rate): + // + // d + // -- s(t) ~= (s[n] - s[n - 1])*fs + // dt + // + // 2 + // d 2 + // --- s(t) ~= (s[n] - 2*s[n - 1] + s[n - 2])*fs + // 2 + // dt + // + // we can obtain a difference equation, and implement it with an IIR digital + // filter. + // + + FLT k = 60; + // adaptation constant. + FLT q = 6; + // friction coefficient. + + FLT a[] = + { + k + GAUGE_RATE*(q + GAUGE_RATE), + -GAUGE_RATE*(q + 2.0*GAUGE_RATE), + GAUGE_RATE*GAUGE_RATE}; + FLT b[] = + { k}; + + LingotGauge* gauge = malloc(sizeof(LingotGauge)); + + gauge->filter = lingot_filter_new( 2, 0, a, b ); + lingot_gauge_compute(gauge, initial_position); + return gauge; + } + +void lingot_gauge_destroy(LingotGauge* gauge) + { + lingot_filter_destroy(gauge->filter); + free(gauge); + } + +void lingot_gauge_compute(LingotGauge* gauge, FLT sample) + { + gauge->position = lingot_filter_filter_sample(gauge->filter, sample); + } + diff --git a/src/lingot-gauge.h b/src/lingot-gauge.h new file mode 100644 index 0000000..44b1a94 --- /dev/null +++ b/src/lingot-gauge.h @@ -0,0 +1,46 @@ +//-*- C++ -*- +/* + * lingot, a musical instrument tuner. + * + * Copyright (C) 2004-2007 Ibán Cereijo Graña, Jairo Chapela Martínez. + * + * This file is part of lingot. + * + * lingot 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. + * + * lingot 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 lingot; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LINGOT_GAUGE_H__ +#define __LINGOT_GAUGE_H__ + +#include "lingot-defs.h" +#include "lingot-filter.h" + +/* + * Implements the dynamic behaviour of the gauge with a digital filter. + */ + +typedef struct _LingotGauge LingotGauge; + +struct _LingotGauge + { + LingotFilter* filter; + FLT position; + }; + +LingotGauge* lingot_gauge_new(FLT); +void lingot_gauge_destroy(LingotGauge*); +void lingot_gauge_compute(LingotGauge*, FLT); + +#endif /*__LINGOT_GAUGE_H__*/ diff --git a/src/lingot-i18n.h b/src/lingot-i18n.h new file mode 100644 index 0000000..cded340 --- /dev/null +++ b/src/lingot-i18n.h @@ -0,0 +1,42 @@ +//-*- C++ -*- +/* + * lingot, a musical instrument tuner. + * + * Copyright (C) 2004-2007 Ibán Cereijo Graña, Jairo Chapela Martínez. + * + * This file is part of lingot. + * + * lingot 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. + * + * lingot 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 lingot; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef LINGOTI18N_H_ +#define LINGOTI18N_H_ + +#include <libintl.h> +#include <locale.h> +#include <langinfo.h> + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef ENABLE_NLS +#undef _ +# define _(String) (const char*) gettext (String) +#else +# define _(String) (String) +#endif + +#endif /*LINGOTI18N_H_*/ diff --git a/src/lingot-logo.xpm b/src/lingot-logo.xpm new file mode 100644 index 0000000..6e17b52 --- /dev/null +++ b/src/lingot-logo.xpm @@ -0,0 +1,343 @@ +/* XPM */ +static const char *lingotlogo[] = { +/* columns rows colors chars-per-pixel */ +"80 80 257 2", +" c black", +". c #2E4E41EA1FB9", +"X c #2F7542BE2093", +"o c #348B44B92376", +"O c #39E8475526C6", +"+ c #3B8D48A42821", +"@ c #3E2349B12992", +"# c #42BB4C972CB8", +"$ c #47474FF73052", +"% c #48FB503430FF", +"& c #4CD853213414", +"* c #51CB55B43725", +"= c #564F5A4C3B43", +"- c #5A7D5D3C3E4E", +"; c #529657CF388C", +": c #5C5B603040B4", +"> c #5E896199422C", +", c #60A75D8440D7", +"< c #63CD64104550", +"1 c #674F67624883", +"2 c #678169444994", +"3 c #6C8E6CCB4D3A", +"4 c #68DA665B4854", +"5 c #6F0671D250C7", +"6 c #70DE6D2F4EF6", +"7 c #7EF96D2055C3", +"8 c #7D3767F552BA", +"9 c #745F74285424", +"0 c #7683792557B9", +"q c #7CB1741A57F4", +"w c #7FD8776C59C7", +"e c #7D4B7CD15BF3", +"r c #7D6D82F15F40", +"t c #79BC89195F75", +"y c #75438A075D75", +"u c #71C8929C6045", +"i c #6D1E94FB5F0A", +"p c #6DA59C5264E9", +"a c #70079ECD6897", +"s c #6FD995DC6258", +"d c #7D7F8B87653F", +"f c #7B278AA06300", +"g c #75C694C46609", +"h c #76F297BD6953", +"j c #73D69D906BB3", +"k c #7CA294916B2C", +"l c #7AEA9C466E26", +"z c #7EFA9DE57191", +"x c #67DCA2C865E8", +"c c #69B6A32F677E", +"v c #6D33A3B96AD7", +"b c #7054A9066EC7", +"n c #72F4A3E06ECE", +"m c #74D0A4A771B2", +"M c #7511AB17734D", +"N c #7AEDA601737E", +"B c #7ABCACAF7811", +"V c #7CD4AF197B14", +"C c #7EFCB2657D9F", +"Z c #84436ED0579C", +"A c #864C6FE35915", +"S c #88DA701159DC", +"D c #820F70D157E3", +"F c #85D473A35B19", +"G c #83777C2A5EF3", +"H c #89E8735A5BF1", +"J c #8C4E794E5F9F", +"K c #85587D7B6153", +"L c #8D7577E36092", +"P c #8DA17B94627A", +"I c #8F237F6B6934", +"U c #92DD7D2E6445", +"Y c #93FC7F2569D2", +"T c #812F81225F81", +"R c #838B84A0628D", +"E c #84518AE36654", +"W c #8F4983806686", +"Q c #8D5485E169D9", +"! c #8CD68D956B97", +"~ c #87268DA668AF", +"^ c #90588ED67342", +"/ c #8D9E92D06DDC", +"( c #857791776C44", +") c #84029CB772D7", +"_ c #8DE597117233", +"` c #8EA19A3D75CF", +"' c #91A88511681E", +"] c #93CC86706B43", +"[ c #949A8BF56DAD", +"{ c #995F833D67AA", +"} c #9A7C850D6B28", +"| c #9D7C8A5F6CA9", +" . c #96588B2B71A4", +".. c #9BC98BA5750F", +"X. c #9F898E617A67", +"o. c #935091BF6FC0", +"O. c #93EC961172E4", +"+. c #94C29BFD7561", +"@. c #97AE9EA37AE0", +"#. c #9A9895AD7646", +"$. c #9A109B6B7728", +"%. c #9B7E9E7579B6", +"&. c #98E9958A7AE9", +"*. c #8443A8D17B68", +"=. c #8120B2D17EA4", +"-. c #96F1A2117A1A", +";. c #9BF6A4EE7CEF", +":. c #9CD1A9A97FC5", +">. c #A17D8C156E36", +",. c #A42E8F787241", +"<. c #A1E18FC77BA7", +"1. c #A6F192E672F6", +"2. c #A39793257D69", +"3. c #AA4795E2753D", +"4. c #AE389A5D78AC", +"5. c #B30D9EE07BFF", +"6. c #B6C7A3137F4A", +"7. c #983F9F0B808C", +"8. c #8C8DAE8E8457", +"9. c #884BB0A5845A", +"0. c #84D2B602836E", +"q. c #8943B971878D", +"w. c #8D8FBB9A8BDB", +"e. c #8BD8B86388AD", +"r. c #95C6A3BD82AE", +"t. c #9F54ACF182B4", +"y. c #9A1DA87E8829", +"u. c #9168BDC38FD9", +"i. c #9701BC539207", +"p. c #A53F960382A8", +"a. c #A6DB9A3684C9", +"s. c #AC659BE684D9", +"d. c #AA7397B180C1", +"f. c #A5A4A40A861B", +"g. c #A1EDADE18417", +"h. c #A988AA688C0F", +"j. c #B018ABF193A6", +"k. c #A3CEB29F8728", +"l. c #A5AAB6FB8A31", +"z. c #A757BB5F8D2C", +"x. c #A981BF438FFC", +"c. c #AA06B6778D5A", +"v. c #AA8BC025916C", +"b. c #AFF6B2629531", +"n. c #B7BAA4C9831B", +"m. c #B9FFA681829E", +"M. c #BA8AA84D8A3E", +"N. c #B95EA8B58C7A", +"B. c #BDA2AE1797A2", +"V. c #B39EABAF95A1", +"C. c #B8B4B69B9CC1", +"Z. c #BC91AF6BA17F", +"A. c #BE02B505A4AF", +"S. c #BD15BCAEA5D5", +"D. c #B8A4BEB9A1FC", +"F. c #AC4FC5299459", +"G. c #AFB7C58C9903", +"H. c #AE87CB4B9844", +"J. c #AEC8CBF898BB", +"K. c #B413C5DE9DB1", +"L. c #B26ECE2A9CF0", +"P. c #B7B9C894A238", +"I. c #B553CFD5A1AE", +"U. c #BA0BC89DA479", +"Y. c #BB3BCA51A68D", +"T. c #BF93CD67AC76", +"R. c #BE7BC86BAA3F", +"E. c #B6DDD175A3D0", +"W. c #BA16D33EA74D", +"Q. c #BDD2D5B2AC06", +"!. c #C1CBAECD87BC", +"~. c #C315AFFE88E3", +"^. c #C5D5B3178B8F", +"/. c #C9C7B7C88EB1", +"(. c #CB2FB8E2903D", +"). c #CE7EBC989254", +"_. c #C684B6F19D30", +"`. c #D224BFD694C3", +"'. c #CA84BE10ABD3", +"]. c #C5FBB9F1A700", +"[. c #D4B0C3559720", +"{. c #D7A2C6AC99DF", +"}. c #D907C7749A12", +"|. c #DD3CCC359DE1", +" X c #C1D1CE48AF76", +".X c #C9DBC334AD40", +"XX c #C571CE8AB36D", +"oX c #CAD0CEDBB923", +"OX c #C105D785AFF8", +"+X c #C3DFD694B323", +"@X c #C548DA3FB579", +"#X c #C808DC02B94B", +"$X c #CC45D553BC6E", +"%X c #CAB8DDA2BCE1", +"&X c #C8DDD37DB87C", +"*X c #D7D2C9AFAB07", +"=X c #D951CCCEB2B0", +"-X c #DE22D322BC6C", +";X c #E140D06EA108", +":X c #E5B3D535A487", +">X c #EA6BD9F5A805", +",X c #EE1ADE3FABCD", +"<X c #E5C7D89CAE0C", +"1X c #E294D538B2DD", +"2X c #E830DB8CB90B", +"3X c #F37AE3D7AF6B", +"4X c #F619E709B22A", +"5X c #F752E925B732", +"6X c #F72CEA14BC70", +"7X c #D000D805C144", +"8X c #CEA1DFD7C17B", +"9X c #D311D51DC431", +"0X c #D29FDA28C4D8", +"qX c #D738DD50CAB4", +"wX c #DB3CDF0ECF59", +"eX c #DB3BD3BCC7E2", +"rX c #DDAADE16D202", +"tX c #CFCFE188C316", +"yX c #D2BAE2E4C6C8", +"uX c #D69AE57BCB88", +"iX c #D9EBE692CF48", +"pX c #DD68E4FCD35D", +"aX c #DE08EA70D50C", +"sX c #E3B1DB62C8FC", +"dX c #E4FEE0ABDAC4", +"fX c #E215DE2AD715", +"gX c #E5AAE293D5A7", +"hX c #E5B0E57EDC9B", +"jX c #E140EC3FD8B8", +"kX c #E45DEE6ADD4C", +"lX c #EC9CE5CAD492", +"zX c #F861EBA7C35E", +"xX c #F8ACEE49CB05", +"cX c #F913EC91C5FE", +"vX c #F958EF30CD2D", +"bX c #F9F4F083D281", +"nX c #F3AFEC22D68B", +"mX c #FA66F1D9D5EB", +"MX c #FB20F421DC8C", +"NX c #EDD8E516CCE0", +"BX c #E7CAF0BAE1C9", +"VX c #EAD5E7ADE2E7", +"CX c #ED07EA54E5DB", +"ZX c #E80DF10EE225", +"AX c #EA9DF261E5B6", +"SX c #EED8F47DEADD", +"DX c #F167F044EC18", +"FX c #F787F2AFE303", +"GX c #F246F639EE99", +"HX c #FC03F658E4BE", +"JX c #FCE7F857E952", +"KX c #FD88F974EA48", +"LX c #F4DDF7FFF1DD", +"PX c #F76AF9F8F4EF", +"IX c #F9B7FB74F7F9", +"UX c #FDC7FE48FD59", +"YX c None", +/* pixels */ +"YXYXYXYXYXYXYXYXZ S H L Y ..<.p.X.X.X.X.X.X.p.X.X.....X...&...X......... ... ... . . .[ .} [ } [ ] ] ] ] ] ] ] Q ] ' ' ' Q Y Q W W W { H H S S YXYXYXYXYXYXYXYX", +"YXYXYXYXYXH H S H ..Z.eXdXVXVXVXVXVXhXhXVXaXrXpXrXrXrXqXqXuX0X0X7X7X7X#X&X$X&XXXXXXXXX XT.T.T.Y.U.U.P.P.K.K.G.G.F.F.F.x.x.x.x.x.F.F.z.:.:.$.W H H H J YXYXYXYXYX", +"YXYXYXYXYXS H Y ].DXUXUXUXUXUXIXPXPXLXLXGXSXSXAXAXAXkXkXkXjXaXaXiXiXiXiXuXyXtXtXtX%X%X#X#X@XQ.#XQ.Q.W.W.W.E.E.E.J.J.J.J.J.J.J.J.J.J.J.J.J.J.F.%.J H H YXYXYXYXYX", +"YXYXYXYXS S p.rXUXUXUXUXUXIXIXIXPXLXGXGXSXSXAXBXAXkXkXkXaXjXaXiXiXiXiXyXyXtXtXtX%X%X#X@X@X+XQ.Q.Q.W.Q.E.E.E.L.J.H.H.J.J.J.J.J.J.J.J.J.J.J.J.J.H.k.' H H YXYXYXYX", +"YXYXYXH S p.CXUXUXUXUXUXIXIXIXLXLXGXGXSXAXAXAXBXkXkXkXkXaXaXiXiXuXuXuXyXyXtX%X%X%X#X@X@X@X+XQ.Q.Q.Q.E.E.E.J.E.J.J.H.J.J.J.J.J.J.J.J.J.J.H.J.H.J.J.x.' H H YXYXYX", +"YXYXS Z <.VXUXUXUXUXUXUXIXPXLXLXLXSXSXAXAXZXBXBXkXaXkXaXiXpXiXiXuXyXyXyXtXtX%X%X#X@X@X@XQ.Q.Q.Q.W.W.E.I.E.J.J.J.J.J.J.J.J.J.J.J.H.J.H.J.J.J.J.J.J.J.z.{ S H YXYX", +"YXH Z Y eXUXUXUXUXUXIXIXPXLXLXLXGXSXAXAXAXZXBXkXkXkXaXaXiXiXiXiXyXyXtXtXtX%X%X#X#X@XQ.@XQ.Q.W.W.W.E.I.E.J.J.J.J.H.J.J.J.J.J.J.J.H.J.H.J.J.J.J.J.J.J.J.k.J H H YX", +"YXH H ].UXUXUXUXUXUXIXIXLXLXGXDXSXAXAXAXAXkXkXkXaXaXaXaXiXiXuXyXyXyXtX%X%X%X#X@X@X@X@XQ.Q.Q.W.W.E.I.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.H.H.J.J.J.J.H.$.H H YX", +"YXA ..CXUXUXUXUXIXIXIXLXLXGXSXSXSXAXAXAXkXkXaXkXaXaXiXiXuXuXuXyXyXtXtX%X%X#X#X@XQ.Q.Q.Q.Q.W.W.E.L.L.L.H.J.J.J.J.J.J.J.J.J.J.H.J.H.J.J.J.J.J.J.J.J.J.J.J.F.W S YX", +"A S ].UXUXUXUXIXIXIXLXLXLXSXSXSXAXBXBXkXaXkXaXaXaXiXiXiXuXuXyXyXtXtX%X%X%X#X@X@XQ.@XQ.Q.W.W.E.E.L.L.H.H.H.H.J.H.H.J.H.J.H.J.H.J.J.J.J.H.J.H.H.J.H.J.J.J.F.$.S S ", +"A Y dXUXUXUXIXIXPXLXLXGXSXSXSXAXAXBXkXkXkXaXaXaXaXiXiXuXuXyXtX%X#XR.D.C.b.h.f.f.f.f.k.h.h.c.G.G.L.L.H.H.J.J.H.J.J.J.J.J.H.J.J.J.H.J.H.J.J.J.J.J.J.J.H.J.H.z.W S ", +"S p.IXUXUXUXIXIXLXLXLXSXSXAXAXAXBXBXkXkXkXaXaXpXiXiXuX7XXXD.j.X.} ' P P U U { } { ' U U L P P ' [ $.:.F.F.J.H.H.J.H.J.H.J.J.H.J.J.J.J.J.J.H.H.J.H.J.J.J.J.F.{ H ", +"S A.UXUXUXIXPXLXLXLXSXSXAXAXAXAXkXkXkXkXjXaXiXpXyXXXj.#.U L U ..s.B.'.*X*X=X2X2X2X=X1X*X{._.M.4.>.U J J ] -.k.F.H.H.J.H.J.H.J.J.J.H.J.J.H.J.J.J.J.H.J.J.J.J.3.H ", +"S eXUXIXIXPXLXLXSXGXSXAXAXAXBXkXkXkXaXaXaXiX&Xb...P Y X.B.=XsXNXnXMXmXmXmXvXvXvXxXxXvXcXcX6X6X4X,X<X}.m.>.U J { %.c.H.J.J.J.H.J.J.J.J.H.J.J.J.J.J.J.H.J.J.J.:.T ", +"L fXUXUXPXLXLXLXGXSXAXAXAXBXkXkXkXkXaXiXXXs.U U <._.-XnXMXMXHXMXbXMXbXbXvXbXxXvXxXcXcXcXcXcX6X6X6X6X6X5X,X|.!.1.U J o.l.H.H.J.J.J.H.H.J.J.J.H.J.H.J.J.J.J.J.:.T ", +"Y dXIXPXLXLXGXGXSXAXAXAXBXkXkXkXaXpX.Xa.P ] N.eXnXHXHXMXMXMXMXmXbXbXbXbXbXvXcXxXcXcXcX6X6X6X6X6X5X5X5X4X4X4X4X,X}.6.U J [ k.H.J.J.J.J.J.J.H.J.J.J.J.J.H.J.J.z.W ", +"<.VXIXLXLXGXSXSXAXAXAXAXkXkXkXaX7Xs.U Y ].sXFXHXHXMXMXMXMXbXmXmXbXbXbXvXxXxXxXzXcXcXzXzX6X5X6X5X5X5X4X4X4X3X4X4X4X3X|.6.{ J #.z.H.H.H.J.H.J.J.J.J.J.J.H.J.J.x.' ", +"X.VXLXLXLXGXSXSXAXAXBXkXkXkXiXA.Y Y B.fXFXHXHXHXMXMXMXMXMXbXbXbXbXbXvXxXxXxXzXzX6XzX6X6X6X5X6X5X4X4X4X4X4X3X4X4X4X4X4X3X:X6.U W ;.F.J.H.J.H.H.J.H.J.J.J.J.J.x.' ", +"X.hXLXGXSXSXSXAXAXBXkXkXkXoXp.L a.eXHXJXHXHXHXMXMXMXMXMXmXbXbXbXvXvXxXxXxXzXzXzXcX6X6X6X6X5X4X5X4X3X4X4X;X4.|.4X4X4X4X4X4X4X}.1.T { :.H.J.H.H.J.J.H.J.H.J.J.x.' ", +"X.hXLXSXSXAXAXAXBXBXkXkXS.Y Y '.nXKXJXHXHXMXHXMXMXMXmXmXbXbXbXbXvXvXxXxXxXzXzXzX6X6X5X6X6X5X4X4X4X4X4X3X6.Z 1.,X4X4X4X4X4X4X4X>X/.{ W 4.H.H.H.H.J.J.J.J.J.J.x.' ", +"X.hXSXSXSXAXAXBXkXkXpXV.L p.sXJXHXHXHXHXHXMXMXMXMXmXmXbXmXvXbXvXvXxXxXcXzXzXzXzX6X6X6X5X4X4X4X4X4X4X4X:X{ J S /.4X4X4X4X4X4X4X4X4X;X1.T +.F.J.J.J.H.J.H.J.J.x.' ", +"X.hXSXAXAXAXBXBXBX9Xa.L N.lXKXJXHXHXHXHXMXMXMXMXMXmXbXbXvXvXvXxXxXxXcXcXzXzX6X5X6X6X5X5X4X4X4X4X4X4X4X(.H ( e Y :X4X4X4X4X4X3X4X4X4X>X6.J | x.J.J.J.J.J.J.J.x.W ", +"X.pXSXAXBXBXkXBXqXp.L ].FXJXJXHXHXHXHXMXMXMXMXMXmXbXbXbXmXvXxXxXcXcXcX6XzXzX6X6X6X5X5X5X4X4X4X4X4X4X3X3.W N y Z m.4X4X4X4X4X4X4X4X3X4X3X^.{ W :.H.H.J.H.J.J.x.' ", +"X.fXAXAXBXBXkXqXp.Y '.FXJXJXHXHXHXHXMXMXMXMXbXbXmXbXbXbXvXvXxXxXcXcXcX6X6XzX6X5X5X5X4X4X4X4X4X4X4X4X>X{ O.=.p e J |.4X3X4X3X4X4X4X4X4X4X3X/.{ W x.J.J.J.J.J.x.{ ", +"X.rXAXZXkXkXwX7.U '.JXJXHXHXHXHXMXMXMXMXMXmXbXbXmXbXbXxXxXxXcXcXcXcX6X6X6X6X6X5X4X4X4X4X3X4X4X4X4X4X).L -.N d f Z 3.3X3X4X4X4X4X4X4X4X4X4X3X).{ ' F.J.H.H.H.F.' ", +"X.rXAXkXkXrXa.I '.JXJXJXHXHXHXMXMXMXMXMXMXmXbXbXbXbXvXxXxXxXcXcXcX6X6X6X6X6X6X4X4X4X4X4X4X4X4X4X4X4X6.P 8.f P ( T S [.3X4X3X4X4X4X4X4X4X4X4X3X/.J [ F.H.H.H.F.' ", +"..iXZXkXaXj.L ].FXJXJXHXHXHXMXMXMXMXMXbXbXbXbXbXvXvXxXxXcXzXzXzX6XcX6X6X6X5X5X4X4X4X4X4X4X4X4X4X4X>X{ ! m e Z ! u D 1.,X4X4X4X3X4X4X4X4X3X4X4X3X^.J $.H.H.H.x.{ ", +"X.qXkXkX'.L V.HXJXJXHXHXHXHXMXMXMXMXMXbXbXbXbXvXvXvXxXcXzXzXzXzX6X6X6X5X5X5X4X3X4X4X4X4X4X4X4X4X5X}.G ` a F Z P ) t H [.4X4X4X4X4X4X3X4X4X4X4X4X4X6.H :.H.H.x.W ", +"..qXBX9X} <.lXKXJXJXHXHXMXMXMXMXMXbXbXbXbXbXvXvXvXxXcXzXcXzXzXzX6X6X5X5X5X4X4X4X4X4X4X4X4X4X4X4X4Xn.P *.u D 1.P +.u G >.>X4X4X4X4X4X4X4X4X4X4X4X4X:X1.W z.J.F.W ", +"..qXrXa.U eXHXHXJXHXHXFXMXMXMXMXMXbXbXbXbXbXvXxXxXcXzXzXzXzX6X6X5X6X5X5X4X4X4X4X4X4X4X4X4X3X4X4X,X| W n r J [.| ! *.u H /.4X4X4X3X4X3X4X4X4X4X3X4X4X[.{ | F.F.W ", +"..0XA.H <.dXHXHXHXHXFXMXMXMXMXMXbXbXbXbXvXvXxXxXcXcXzXzX6X6X6X6X5X5X5X4X4X4X4X3X4X4X4X3X3X4X4X4X}.J ( v e | 3Xm.J :.a T 3.3X4X3X4X4X4X4X3X4X3X4X4X4X;X1.H ;.F.' ", +"..7XoX7.U ..'.nXFXMXMXMXMXMXbXbXbXbXbXbXvXxXcXxXcXzXzX6X6X6X6X6X6X5X4X4X3X4X4X4X4X4X4X4X4X4X4X3X!.J l g D 6.4X).G r.b T W :X4X4X3X4X4X3X4X4X4X4X>X^.| J o.:.F.W ", +"X.0XaXuXS.<.L <..XnXMXMXMXmXmXmXmXbXvXxXxXxXxXxX6XzX6X6X6X6X6X6X5X4X4X3X4X4X4X3X3X4X4X4X4X4X4X3X>.W n t Z {.4X|.J +.V d F {.4X4X4X4X4X4X4X4X>X/.>.J ' :.F.J.F.{ ", +" .$XiXuXuX%XC. .U <.*XnXmXMXvXmXvXvXxXxXcXcXcXzXzXzX6X6X6X6X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X3X|.U ! v e { :X4X,X' .8.d S [.4X4X4X4X4X4X>X[.1.J { :.H.J.J.J.x.W ", +"..$XiXuXuXuXtX&Xb.] L d.=XxXvXvXvXvXxXxXcXxXzX6X6X6X6X5X5X5X5X4X4X3X4X3X3X4X3X4X4X3X4X4X4X4X4X!.J ) u D 6.3X3X>X{ .9.E Z {.5X4X4X4X3X[.1.J { ;.F.J.H.H.J.J.F.W ", +"X.$XuXuXyXtXtXtX#XXXh.U U s.=XvXvXxXcXcXcXcXzX6X6X6X5X5X5X4X4X4X4X4X4X4X4X4X4X4X4X4X3X4X4X4X3X3.T n y A (.4X4X;XH _ 9.d H }.5X4X3X}.3.U W $.F.F.H.H.J.H.J.J.z.W ", +" .$XuXyXyXtX%X%X#X#X@XR.2.' U n.1XcXcXzXxX6XzX6X6X6X5X5X4X4X4X4X4X4X4X3X4X3X3X3X3X3X4X4X4X4X:XP ! v r J :X4X3X~.F -.*.r { :X3X|.6.W J %.F.J.J.J.H.H.J.J.J.J.F.T ", +"..&XyXtXtX%X%X%X%X#X+X@XOXK.%.P ' M.1XzXcX6X6X6X6X6X5X5X4X4X4X4X4X4X3X>X{.^.6.6.6.n.~.[.:X4X/.Z ) p F >.4X4X;XU K *.l F 1.|.6.U J +.l.H.H.J.J.H.H.H.H.J.J.J.F.{ ", +"| &XyX8XtX%X%X#X#X#X@X+XQ.Q.T.v.#.J } B.<X6X6X5X5X5X6X4X4X4X3X4X3X}.6.{ U J J J F H L P } n.} P n u Z ~.4X|.| Z d N E Z >.{ J o.l.H.H.H.H.H.J.J.H.H.J.J.J.J.F.W ", +" .&XtX8X%X%X#X@X@XQ.OXQ.Q.Q.Q.W.L.c.[ J | ^.<X6X5X5X4X4X4X4X4X;X6.U J [ o.R J J P J G Q [ H 8 Q j T J |.,X>.Z E l k D Z J o.k.J.J.H.H.H.H.H.H.J.H.H.J.H.J.J.F.W ", +" .XX%X%X%X#X@X@XOXOXOXQ.Q.W.W.E.I.L.H.g.[ J >./.,X3X4X3X4X4X[.{ J o.:.] K .&.r.@. .W F ^ ^ S k a w | 3X`.L d m l K Z Q g.F.J.J.J.J.H.J.H.J.J.J.J.J.J.H.H.H.F.' ", +" .XXtX%X#X#X@X+XOXOXQ.Q.E.E.E.I.L.L.L.J.G.:.Q J >.).,X4X3X`.{ U k.k.R ' y.i.i.u.w.w.8.` K 7 K l g Z 4.4X`.P d k K F @.G.J.J.J.J.H.J.J.J.H.J.H.J.H.H.J.J.H.H.l.{ ", +" . X%X#X#X@X@X+XQ.Q.Q.W.W.E.I.L.J.L.J.J.H.L.F.;.W J 1.[.}.U ' z.G.K U y.u.u.w.q.q.0.0.9.) L e a f 8 U {.(.H 7 H K t.H.H.J.J.J.J.J.J.H.J.J.H.J.J.J.J.J.J.H.J.z.W ", +"| X%X@X@X@XQ.Q.Q.Q.W.W.E.L.L.L.J.J.J.J.H.H.H.H.x.;.W U U U l.J.+.F y.u.w.q.q.q.0.=.V M m k h n G F H U U P [ :.G.H.H.H.J.J.J.J.H.J.J.J.J.J.J.H.H.J.J.J.J.J.F.W ", +"[ T.#X#XQ.@XQ.Q.Q.W.W.E.L.L.L.J.J.J.J.J.H.H.H.J.J.J.F.+.W :.H.F.K Q w.q.0.0.0.C V b v v v v v h q ! t.I %.x.J.J.J.J.J.J.J.J.J.J.J.H.J.H.H.J.J.J.J.J.J.J.H.H.F.W ", +"} T.@X@XQ.Q.Q.Q.W.E.E.L.L.L.L.J.H.J.H.J.H.H.J.J.H.J.H.F.F.H.H.z.F +.0.0.C 0.C B b c c v v v m d Z :.F.F.J.J.J.J.J.F.J.J.J.J.J.J.J.H.J.J.J.J.H.J.J.H.J.H.H.H.F.W ", +" .Y.@XQ.Q.Q.Q.W.W.E.L.L.L.L.H.J.J.J.J.H.J.J.H.J.H.J.J.J.J.J.J.k.7 ) =.V V B M c p c c v v n n K F z.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.H.J.J.J.H.H.H.F.' ", +"] U.Q.+XQ.Q.W.W.E.E.L.L.J.H.J.J.H.J.J.J.H.H.J.J.J.H.J.J.J.J.J.t.Z h V V M M v x c v v v b m a q Q J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.H.J.H.J.H.J.J.H.H.z.' ", +" .U.Q.Q.Q.W.W.E.J.I.L.J.J.J.J.J.H.J.J.J.J.H.H.J.J.J.J.H.H.J.J.k.Z g b b n c c x v v v v n m k Z @.J.J.J.J.J.H.J.J.H.J.J.H.J.J.H.H.J.J.J.J.H.J.J.J.J.H.J.J.J.F.W ", +"} U.Q.Q.W.W.I.E.E.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.H.J.J.J.J.J.z.F r c v c c c v v v v v m n G F z.J.J.J.H.J.J.H.H.J.H.J.J.H.H.J.J.J.H.J.J.J.H.J.H.J.J.J.H.J.F.W ", +"! P.Q.W.W.I.E.E.J.J.J.J.J.J.J.J.H.J.J.J.H.J.H.H.J.J.J.H.H.J.H.H.o.w i x x c c v v m v m m h F O.H.J.J.J.H.J.H.J.J.J.H.H.J.J.J.J.H.J.H.J.J.J.J.J.J.J.H.J.H.H.F.' ", +"] P.W.E.E.E.L.J.J.J.J.J.J.J.J.J.J.J.H.H.J.J.J.J.H.H.J.J.H.H.H.J.z.J w p c c v v v v m m j G K z.J.J.J.J.J.J.J.J.J.H.J.J.H.H.J.H.J.J.J.J.H.J.H.J.J.H.J.J.H.H.z.' ", +"' K.W.E.I.J.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.H.H.J.J.;.F r p v v b m n m j e F :.H.J.J.J.H.J.J.H.J.H.J.J.H.J.J.H.J.H.J.J.J.J.J.J.J.H.J.H.J.J.J.z.W ", +"' K.E.I.E.J.J.H.J.J.J.J.J.J.J.J.H.J.J.J.H.H.J.H.H.J.H.J.J.J.J.J.J.H.;.J F r g h h g f K F -.H.H.J.J.J.J.H.J.J.J.J.H.J.J.H.J.J.H.J.J.J.H.H.J.J.J.J.J.J.J.J.J.F.' ", +"] G.I.I.J.J.J.H.H.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.H.H.J.H.J.J.H.k.! F F F F Z 7 I t.J.J.J.J.H.J.H.J.J.J.J.J.H.J.H.H.J.J.H.H.J.H.J.J.J.J.J.H.J.J.J.J.J.F.W ", +"] G.I.J.G.@.O.l.F.J.J.J.J.J.J.J.H.J.J.J.H.J.H.J.J.H.J.H.J.J.J.J.J.J.J.J.F.z.+.o.o.O.y.F.J.J.J.H.J.J.J.J.J.H.J.H.H.J.J.H.J.J.H.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.F.W ", +"' F.L.L.-.; # 5 F.H.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.H.J.J.J.J.H.J.F.F.H.J.J.H.H.F.' ", +"' F.J.J._ # . 1 x.J.J.J.J.J.J.J.J.J.J.J.H.J.H.J.H.J.H.J.J.J.J.J.J.J.J.F.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.H.J.H.J.J.J.J.J.J.H.J.J.F.T 3 -.H.L.H.H.z.' ", +"' x.J.J.+.& o e F.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.H.J.J.J.J.H.J.H.J.H.H.J.F.+.$ o - +.:.z.H.z.' ", +"Q F.J.J.+.$ + T G.F.J.J.J.J.J.J.J.J.J.J.J.J.J.H.J.H.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.F.J.J.J.J.J.J.H.J.J.H.J.J.J.H.H.z.O.r - o X o $ * 3 :.F.' ", +"' z.H.J._ $ + ~ F.J.J.J.J.J.F.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.F.F.F.J.J.J.J.J.J.J.J.H.H.J.J.J.H.J.J.J.J.F.0 # o X X X o + + & #.F.' ", +"' F.J.J._ # + o.J.J.J.J.J.J.J.J.J.J.J.J.z./ E :.F.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.F.t.T 0 T t.J.J.J.J.J.J.J.H.F.F.F.H.J.H.J.J.J.F.T > > $ . O 2 T ! +.F.z.' ", +"U F.J.J._ # + O.J.J.J.J.J.J.J.J.J.J.J.J.+.& O 9 z.J.J.J.H.z.-.l.J.J.F.J.J.J.J.J.J.J.J.-.> O . + 0 F.J.J.J.J.J.x./ 5 2 5 ` z.J.J.J.H.H.F.l.:.1 . $ +.J.J.J.J.x.Q ", +"T F.J.J./ # + +.J.J.J.J.J.J.J.J.J.J.J.J.:.6 < / H.J.J.J.z.0 ; e k./ r -.F.J.J.J.J.J.z.5 o @ O o 5 x.J.J.J.J.F.~ & + + o # 0 F.J.J.J.H.H.H.F.> . * :.J.J.H.J.x.Q ", +"U z.L.H./ # + +.J.J.J.J.J.J.J.H.J.J.J.H.-.< < ;.L.J.J.J.:.* . - < # O ; / J.H.H.J.J.:.- o 7 = X 0 H.J.J.J.J.F.4 X - 0 & X % / F.H.H.J.J.J.:.- X = l.J.J.J.J.z.J ", +"J l.J.J.! @ # +.J.J.J.J.J.J.J.H.J.H.J.F.9 o # T J.J.J.J.:.* . o X # # X < F.H.H.J.J.:.- O , % X 6 F.J.J.J.J.:.- o T F.! & o = +.J.H.J.J.J.;.& X < z.J.J.J.J.l.H ", +"H :.L.H.! + + O.H.H.J.J.J.J.J.H.J.J.J.F.1 X * ;.J.J.J.J.+.$ . . # T G o % $.H.H.J.J.H.9 o X X X - :.J.J.H.H.F.- O r H.J.T O o T F.J.J.J.J.! + o 5 F.J.H.J.J.k.H ", +"H $.J.H.T o + 6 T ! +.+.:.k.F.H.J.J.J.:.= X - z.J.J.J.J.! @ . O 9 F.~ o + / H.H.J.J.J.:.6 - - # @ / J.J.H.H.F.9 O > :.:.T O X T F.J.J.J.J.~ O O T F.J.H.J.J.$.H ", +"S ! H.l.2 X X o @ # @ # * - e z.J.J.J.;.& o 3 F.H.H.H.H.T # . = :.H./ # # T F.J.J.J.L.J.F.F.:.r O 3 :.H.J.J.H.$.; + > < # o - +.J.H.J.J.F.T O O / H.H.H.J.F.] S ", +"S J l.F.T < < 3 5 5 3 1 - & 4 -.J.J.J.:.1 - _ H.H.H.H.H.-.2 < ! H.H.:.2 * T F.J.H.F.:.H.H.H.J.+.% # / H.J.J.H.H.+.< & & = 3 +.F.J.J.J.J.H.+.3 3 g.J.H.H.J.z.J S ", +"S H 3.H.F.l.l.F.F.F.H.x.k.-.:.H.J.J.J.H.k.:.H.J.H.H.H.H.F.F.l.H.H.H.H.:.-.F.H.J.H.T < T F.H.H.F.3 o 3 F.J.H.H.H.J.z.-.;.:.F.H.H.J.J.H.J.J.H.:.H.H.H.J.J.J.+.H S ", +"YXS T F.J.H.H.H.J.J.J.J.J.J.J.J.J.J.J.J.H.H.H.H.J.H.H.H.H.J.J.H.H.H.H.H.H.H.J.J.F.r o & T :.:.:.> o 5 F.J.H.H.H.J.J.J.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.x.' H YX", +"YXH S $.H.H.H.J.J.J.J.H.J.J.J.J.J.H.J.H.J.J.J.J.J.J.J.J.H.H.J.J.J.J.H.J.H.J.J.J.J.:.3 # + = = * @ - +.H.J.H.J.H.J.H.J.J.J.J.J.J.H.J.H.J.J.J.J.J.J.J.J.H.$.H H YX", +"YXH H J k.J.H.H.J.H.J.J.J.J.J.J.J.J.J.J.H.J.H.H.J.H.J.H.J.J.H.J.H.J.J.J.H.J.H.J.J.L.:.~ 9 > 2 3 T :.H.H.J.J.J.J.J.J.H.J.H.J.H.J.J.J.J.J.J.H.H.J.H.J.L.:.P S H YX", +"YXYXH S Q z.J.J.J.H.J.H.J.J.J.J.H.J.H.J.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.J.J.H.J.J.J.J.J.J.F.:.F.F.H.H.H.H.H.J.H.H.J.J.J.J.J.J.H.H.J.J.H.J.H.H.H.H.H.H.F.W S H YXYX", +"YXYXYXH H [ x.J.J.J.J.J.J.J.J.J.J.J.J.J.J.H.H.J.H.J.H.J.J.J.J.H.H.J.J.J.J.J.J.H.J.J.J.J.J.L.H.H.H.H.H.H.J.J.H.H.H.J.H.J.H.J.H.H.H.J.H.J.H.H.H.H.H.F.{ H H YXYXYX", +"YXYXYXYXH H Q k.H.J.J.J.J.J.J.J.H.J.J.J.H.H.H.H.J.H.H.H.J.J.J.J.J.J.J.J.H.H.H.H.J.J.J.J.H.H.H.H.H.H.H.H.H.H.H.H.J.J.H.H.H.H.H.H.J.J.J.J.J.J.H.H.:./ H H YXYXYXYX", +"YXYXYXYXYXH H P %.x.J.J.J.J.J.J.J.J.J.J.H.F.H.H.J.H.H.H.J.J.J.J.J.J.J.J.H.H.H.F.J.J.J.J.H.F.H.H.H.H.H.H.J.J.H.H.J.J.H.F.J.H.H.H.J.J.J.L.J.J.F.$.W H H YXYXYXYXYX", +"YXYXYXYXYXH H H J U #.:.z.z.x.x.F.F.F.F.F.F.z.F.F.F.F.l.F.F.F.F.F.z.F.F.F.F.F.F.F.F.F.F.F.F.z.F.F.F.z.F.F.F.F.z.F.F.F.F.F.F.F.z.F.F.z.:.:.$.W H S S S YXYXYXYXYX", +"YXYXYXYXYXYXYXYXJ S S J J ' ' ' W ' { T W { W W W W W W W W W W W W W ' ' T W { T { W W { W W W W W W W W W W W W W W W W W W W W { W J W H S S YXYXYXYXYXYXYXYX" +}; diff --git a/src/lingot-mainframe.c b/src/lingot-mainframe.c new file mode 100644 index 0000000..a98c16d --- /dev/null +++ b/src/lingot-mainframe.c @@ -0,0 +1,766 @@ +//-*- C++ -*- +/* + * lingot, a musical instrument tuner. + * + * Copyright (C) 2004-2007 Ibán Cereijo Graña, Jairo Chapela Martínez. + * + * This file is part of lingot. + * + * lingot 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. + * + * lingot 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 lingot; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdio.h> +#include <math.h> +#include <unistd.h> +#include <signal.h> +#include <string.h> + +#include "lingot-defs.h" + +#include "lingot-config.h" +#include "lingot-mainframe.h" +#include "lingot-config-dialog.h" +#include "lingot-gauge.h" +#include "lingot-i18n.h" + +#include "lingot-background.xpm" +#include "lingot-logo.xpm" + +void lingot_mainframe_redraw(LingotMainFrame*); +void lingot_mainframe_put_frequency(LingotMainFrame*); +void lingot_mainframe_draw_gauge(LingotMainFrame*); +void lingot_mainframe_draw_spectrum(LingotMainFrame*); + +GdkColor black_color; +GdkColor gauge_color; +GdkColor spectrum_background_color; +GdkColor spectrum_color; +GdkColor noise_threshold_color; +GdkColor grid_color; +GdkColor freq_color; + +// sizes + +int gauge_size_x = 160; +int gauge_size_y = 100; + +int spectrum_size_y = 64; + +// spectrum area margins +int spectrum_bottom_margin = 16; +int spectrum_top_margin = 12; +int spectrum_x_margin = 15; + +GtkWidget* view_spectrum_item; +GtkWidget* spectrum_frame; + +PangoFontDescription* spectrum_legend_font_desc; + +void lingot_mainframe_callback_redraw(GtkWidget* w, GdkEventExpose* e, + LingotMainFrame* frame) { + if (frame->core->running) + lingot_mainframe_redraw(frame); +} + +void lingot_mainframe_callback_destroy(GtkWidget* w, LingotMainFrame* frame) { + if (frame->core->running) { + g_source_remove(frame->visualization_timer_uid); + g_source_remove(frame->calculation_timer_uid); + g_source_remove(frame->freq_timer_uid); + gtk_main_quit(); + } +} + +void lingot_mainframe_callback_about(GtkWidget* w, LingotMainFrame* frame) { + if (frame->core->running) { + static const gchar* authors[] = { + "Ibán Cereijo Graña <ibancg@gmail.com>", + "Jairo Chapela Martínez <jairochapela@gmail.com>", NULL }; + + const gchar* artists[] = { "Matthew Blissett (Logo design)", NULL }; + + gtk_show_about_dialog(NULL, + "name", "Lingot", + "version", VERSION, + "copyright", "\xC2\xA9 2004-2007 Ibán Cereijo Graña\n\xC2\xA9 2004-2007 Jairo Chapela Martínez", + "comments", _("Accurate and easy to use musical instrument tuner"), + "authors", authors, + "artists", artists, + "translator-credits", _("translator-credits"), + "logo-icon-name", "lingot-logo", + NULL); + } +} + +void lingot_mainframe_callback_view_spectrum(GtkWidget* w, + LingotMainFrame* frame) { + if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(view_spectrum_item))) { + gtk_widget_hide(spectrum_frame); + } else { + gtk_widget_show(spectrum_frame); + } +} + +void lingot_mainframe_callback_config_dialog(GtkWidget* w, + LingotMainFrame* frame) { + if (frame->core->running) { + if (!frame->config_dialog) { + frame->config_dialog = lingot_config_dialog_new(frame); + } else { + // TODO: activate config dialog + } + } +} + +/* Callback for visualization */ +gboolean lingot_mainframe_callback_visualization(gpointer data) { + unsigned int period; + + LingotMainFrame* frame = (LingotMainFrame*) data; + + if (frame->core->running) { + lingot_mainframe_draw_gauge(frame); + + period = 1000/frame->conf->visualization_rate; + frame->visualization_timer_uid = g_timeout_add(period, + lingot_mainframe_callback_visualization, frame); + } + + return 0; +} + +/* Callback for calculation */ +gboolean lingot_mainframe_callback_calculation(gpointer data) { + unsigned int period; + + LingotMainFrame* frame = (LingotMainFrame*) data; + + if (frame->core->running) { + lingot_mainframe_draw_spectrum(frame); + + period = 1000/frame->conf->calculation_rate; + frame->calculation_timer_uid = g_timeout_add(period, + lingot_mainframe_callback_calculation, frame); + } + + return 0; +} + +/* Callback for frequency calculation */ +gboolean lingot_mainframe_callback_frequency(gpointer data) { + unsigned int period; + LingotMainFrame* frame = (LingotMainFrame*) data; + + if (frame->core->running) { + lingot_mainframe_put_frequency(frame); + + period = 1000/GAUGE_RATE; + frame->freq_timer_uid = g_timeout_add(period, + lingot_mainframe_callback_frequency, frame); + } + + return 0; +} + +void lingot_mainframe_color(GdkColor* color, int red, int green, int blue) { + color->red = red; + color->green = green; + color->blue = blue; +} + +LingotMainFrame* lingot_mainframe_new(int argc, char *argv[]) { + GtkWidget* vertical_box; + GtkWidget* horizontal_box; + GtkWidget* file_menu; + GtkWidget* edit_menu; + GtkWidget* help_menu; + GtkWidget* preferences_item; + GtkWidget* quit_item; + GtkWidget* about_item; + GtkAccelGroup* accel_group; + GtkWidget* menu_bar; + GtkWidget* file_item; + GtkWidget* edit_item; + GtkWidget* help_item; + GtkWidget* frame1; + GtkWidget* frame3; + GtkWidget* vbinfo; + LingotMainFrame* frame; + unsigned int period; + + frame = malloc(sizeof(LingotMainFrame)); + + frame->config_dialog = NULL; + frame->pix_stick = NULL; + + frame->conf = lingot_config_new(); + lingot_config_load(frame->conf, CONFIG_FILE_NAME); + + frame->gauge = lingot_gauge_new(frame->conf->vr); // gauge in rest situation + frame->core = lingot_core_new(frame->conf); + + // ----- FREQUENCY FILTER CONFIGURATION ------ + + // low pass IIR filter. + FLT freq_filter_a[] = + { 1.0, -0.5}; + FLT freq_filter_b[] = + { 0.5}; + + frame->freq_filter= lingot_filter_new( 1, 0, freq_filter_a, freq_filter_b); + + // --------------------------------------------------- + + gtk_init(&argc, &argv); + gtk_set_locale(); + + // creates the window + frame->win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_position(GTK_WINDOW(frame->win), GTK_WIN_POS_CENTER); + + GdkPixbuf* logo = gdk_pixbuf_new_from_xpm_data(lingotlogo); + gtk_icon_theme_add_builtin_icon("lingot-logo", 64, logo); + + gtk_window_set_icon(GTK_WINDOW(frame->win), logo); + + // g_object_unref(logo); + + gtk_window_set_title(GTK_WINDOW(frame->win), _("lingot")); + + gtk_container_set_border_width(GTK_CONTAINER(frame->win), 6); + + // fixed size + gtk_window_set_resizable(GTK_WINDOW(frame->win), FALSE); + // tab organization by following container + vertical_box = gtk_vbox_new(FALSE, 0); + gtk_container_add(GTK_CONTAINER(frame->win), vertical_box); + + file_menu = gtk_menu_new(); + edit_menu = gtk_menu_new(); + help_menu = gtk_menu_new(); + GtkWidget* view_menu = gtk_menu_new(); + + accel_group = gtk_accel_group_new(); + + /* menu elements */ + preferences_item = gtk_image_menu_item_new_from_stock( + GTK_STOCK_PREFERENCES, accel_group); + quit_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, accel_group); + about_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ABOUT, + accel_group); + view_spectrum_item= gtk_check_menu_item_new_with_label(_("Spectrum")); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(view_spectrum_item), + TRUE); + + /* addition */ + gtk_menu_append(GTK_MENU(file_menu), quit_item); + gtk_menu_append(GTK_MENU(edit_menu), preferences_item); + gtk_menu_append(GTK_MENU(view_menu), view_spectrum_item); + gtk_menu_append(GTK_MENU(help_menu), about_item); + + gtk_widget_add_accelerator(preferences_item, "activate", accel_group, 'o', + GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); + + gtk_widget_add_accelerator(quit_item, "activate", accel_group, 'q', + GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); + + gtk_window_add_accel_group(GTK_WINDOW(frame->win), accel_group); + + gtk_signal_connect(GTK_OBJECT(preferences_item), "activate", + GTK_SIGNAL_FUNC(lingot_mainframe_callback_config_dialog), frame); + + gtk_signal_connect(GTK_OBJECT(quit_item), "activate", + GTK_SIGNAL_FUNC(lingot_mainframe_callback_destroy), frame); + + gtk_signal_connect(GTK_OBJECT(about_item), "activate", + GTK_SIGNAL_FUNC(lingot_mainframe_callback_about), frame); + + gtk_signal_connect(GTK_OBJECT(view_spectrum_item), "activate", + GTK_SIGNAL_FUNC(lingot_mainframe_callback_view_spectrum), frame); + + menu_bar = gtk_menu_bar_new(); + gtk_widget_show(menu_bar); + gtk_box_pack_start_defaults(GTK_BOX(vertical_box), menu_bar); + + file_item = gtk_menu_item_new_with_mnemonic(_("_File")); + edit_item = gtk_menu_item_new_with_mnemonic(_("_Edit")); + GtkWidget* view_item = gtk_menu_item_new_with_mnemonic(_("_View")); + help_item = gtk_menu_item_new_with_mnemonic(_("_Help")); + gtk_menu_item_right_justify(GTK_MENU_ITEM(help_item)); + + gtk_menu_item_set_submenu(GTK_MENU_ITEM(file_item), file_menu); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(edit_item), edit_menu); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(view_item), view_menu); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(help_item), help_menu); + + gtk_menu_bar_append(GTK_MENU_BAR(menu_bar), file_item); + gtk_menu_bar_append(GTK_MENU_BAR(menu_bar), edit_item); + gtk_menu_bar_append(GTK_MENU_BAR(menu_bar), view_item); + gtk_menu_bar_append(GTK_MENU_BAR(menu_bar), help_item); + +#ifdef GTK12 + gtk_menu_bar_set_shadow_type( GTK_MENU_BAR (menu_bar), GTK_SHADOW_NONE ); +#endif + + //////////////////////////////////////////////////// + + // a fixed container to put the two upper frames in fixed positions + horizontal_box = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start_defaults(GTK_BOX(vertical_box), horizontal_box); + + // gauge frame + frame1 = gtk_frame_new(_("Deviation")); + // gtk_fixed_put(GTK_FIXED(fix), frame1, 0, 0); + gtk_box_pack_start(GTK_BOX(horizontal_box), frame1, FALSE, FALSE, 0); + + // note frame + frame3 = gtk_frame_new(_("Note")); + //gtk_fixed_put(GTK_BOX(hb), frame3, 164, 0); + gtk_box_pack_start(GTK_BOX(horizontal_box), frame3, TRUE, TRUE, 0); + + // spectrum frame at bottom + spectrum_frame = gtk_frame_new(_("Spectrum")); + gtk_box_pack_end_defaults(GTK_BOX(vertical_box), spectrum_frame); + + // for gauge drawing + frame->gauge_area = gtk_drawing_area_new(); + gtk_widget_set_size_request(GTK_WIDGET(frame->gauge_area), gauge_size_x, + gauge_size_y); + gtk_container_add(GTK_CONTAINER(frame1), frame->gauge_area); + + // for spectrum drawing + GtkObject* adjust = gtk_adjustment_new(0.0, 0.0, ((frame->conf->fft_size + > 256) ? 0.5 : 1.0)*frame->conf->sample_rate, 1.0, 100.0, 100.0); + frame->spectrum_scroll = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new( + GTK_ADJUSTMENT(adjust), NULL)); + frame->spectrum_area = gtk_drawing_area_new(); + + int + x = ((frame->conf->fft_size > 256) ? (frame->conf->fft_size >> 1) + : 256) + 2*spectrum_x_margin; + int y = spectrum_size_y + spectrum_bottom_margin + spectrum_top_margin; + + gtk_widget_set_size_request(GTK_WIDGET(frame->spectrum_area), x, y); + gtk_scrolled_window_set_policy(frame->spectrum_scroll, + (frame->conf->fft_size > 512) ? GTK_POLICY_ALWAYS + : GTK_POLICY_NEVER, GTK_POLICY_NEVER); + gtk_scrolled_window_add_with_viewport(frame->spectrum_scroll, + frame->spectrum_area); + gtk_widget_set_size_request(GTK_WIDGET(frame->spectrum_scroll), 260 + 2 + *spectrum_x_margin, spectrum_size_y + spectrum_bottom_margin + + spectrum_top_margin + 4 + + ((frame->conf->fft_size > 512) ? 16 : 0)); + gtk_container_add(GTK_CONTAINER(spectrum_frame), + GTK_WIDGET(frame->spectrum_scroll)); + + // for note and frequency displaying + vbinfo = gtk_vbox_new(FALSE, 0); + gtk_widget_set_size_request(GTK_WIDGET(vbinfo), 96 + 2*spectrum_x_margin, + gauge_size_y); + gtk_container_add(GTK_CONTAINER(frame3), vbinfo); + + frame->freq_label = gtk_label_new(_("freq")); + gtk_box_pack_start_defaults(GTK_BOX(vbinfo), frame->freq_label); + + frame->error_label = gtk_label_new(_("err")); + gtk_box_pack_end_defaults(GTK_BOX(vbinfo), frame->error_label); + + frame->note_label = gtk_label_new(_("note")); + gtk_widget_set_name(frame->note_label, "label_nota"); + gtk_box_pack_end_defaults(GTK_BOX(vbinfo), frame->note_label); + + // show all + gtk_widget_show_all(frame->win); + + // two pixmaps for double buffer in gauge and spectrum drawing + // (virtual screen) + gdk_pixmap_new(frame->gauge_area->window, gauge_size_x, gauge_size_y, -1); + frame->pix_spectrum= gdk_pixmap_new(frame->spectrum_area->window, x, y, -1); + + // GTK signals + gtk_signal_connect(GTK_OBJECT(frame->gauge_area), "expose_event", + GTK_SIGNAL_FUNC(lingot_mainframe_callback_redraw), frame); + gtk_signal_connect(GTK_OBJECT(frame->spectrum_area), "expose_event", + GTK_SIGNAL_FUNC(lingot_mainframe_callback_redraw), frame); + gtk_signal_connect(GTK_OBJECT(frame->win), "destroy", + GTK_SIGNAL_FUNC(lingot_mainframe_callback_destroy), frame); + + period = 1000/frame->conf->visualization_rate; + frame->visualization_timer_uid = g_timeout_add(period, + lingot_mainframe_callback_visualization, frame); + + period = 1000/frame->conf->calculation_rate; + frame->calculation_timer_uid = g_timeout_add(period, + lingot_mainframe_callback_calculation, frame); + + period = 1000/GAUGE_RATE; + frame->freq_timer_uid = g_timeout_add(period, + lingot_mainframe_callback_frequency, frame); + + lingot_mainframe_color(&gauge_color, 0xC000, 0x0000, 0x2000); + lingot_mainframe_color(&spectrum_background_color, 0x1111, 0x3333, 0x1111); + lingot_mainframe_color(&spectrum_color, 0x2222, 0xEEEE, 0x2222); + lingot_mainframe_color(&noise_threshold_color, 0x8888, 0x8888, 0x2222); + lingot_mainframe_color(&grid_color, 0x9000, 0x9000, 0x9000); + lingot_mainframe_color(&freq_color, 0xFFFF, 0x2222, 0x2222); + + gdk_color_alloc(gdk_colormap_get_system(), &gauge_color); + gdk_color_alloc(gdk_colormap_get_system(), &spectrum_color); + gdk_color_alloc(gdk_colormap_get_system(), &spectrum_background_color); + gdk_color_alloc(gdk_colormap_get_system(), &noise_threshold_color); + gdk_color_alloc(gdk_colormap_get_system(), &grid_color); + gdk_color_alloc(gdk_colormap_get_system(), &freq_color); + gdk_color_black(gdk_colormap_get_system(), &black_color); + + spectrum_legend_font_desc + =pango_font_description_from_string("Helvetica Plain 7"); + + return frame; +} + +void lingot_mainframe_destroy(LingotMainFrame* frame) { + lingot_gauge_destroy(frame->gauge); + lingot_core_destroy(frame->core); + lingot_filter_destroy(frame->freq_filter); + lingot_config_destroy(frame->conf); + if (frame->config_dialog) + lingot_config_dialog_destroy(frame->config_dialog); + + // pango_font_description_free(spectrum_legend_font_desc); + // gtk_widget_destroy(frame->freq_label); + // gtk_widget_destroy(frame->error_label); + // gtk_widget_destroy(frame->note_label); + // gtk_widget_destroy(frame->win); + + // gdk_color_free(&gauge_color); + // gdk_color_free(&spectrum_color); + // gdk_color_free(&spectrum_background_color); + // gdk_color_free(&noise_threshold_color); + // gdk_color_free(&grid_color); + // gdk_color_free(&freq_color); + + free(frame); +} + +void lingot_mainframe_run(LingotMainFrame* frame) { + lingot_core_start(frame->core); + gtk_main(); + lingot_core_stop(frame->core); + lingot_mainframe_destroy(frame); +} +// --------------------------------------------------------------------------- + +void lingot_mainframe_redraw(LingotMainFrame* frame) { + lingot_mainframe_draw_gauge(frame); + lingot_mainframe_draw_spectrum(frame); +} + +// --------------------------------------------------------------------------- + +void lingot_mainframe_draw_gauge(LingotMainFrame* frame) { + GdkGC* gc = frame->gauge_area->style->fg_gc[frame->gauge_area->state]; + GdkWindow* w = frame->gauge_area->window; + GdkGCValues gv; + + gdk_gc_get_values(gc, &gv); + + static FLT gauge_size = 90.0; + FLT max = 1.0; + + // draws background + if (!frame->pix_stick) { + frame->pix_stick = gdk_pixmap_create_from_xpm_d( + frame->gauge_area->window, NULL, + NULL, background2_xpm); + } + gdk_draw_pixmap(frame->gauge_area->window, gc, frame->pix_stick, 0, 0, 0, + 0, 160, 100); + + // and draws gauge + gdk_gc_set_foreground(gc, &gauge_color); + + gdk_draw_line(w, gc, gauge_size_x >> 1, gauge_size_y - 1, + (gauge_size_x>> 1) + (int)rint(gauge_size + *sin(frame->gauge->position *M_PI/(1.5*max))), gauge_size_y + - 1- (int)rint(gauge_size *cos(frame->gauge->position*M_PI + /(1.5*max)))); + + // black edge. + gdk_gc_set_foreground(gc, &black_color); + gdk_draw_rectangle(w, gc, FALSE, 0, 0, gauge_size_x - 1, gauge_size_y - 1); + + gdk_draw_pixmap(frame->gauge_area->window, gc, w, 0, 0, 0, 0, gauge_size_x, + gauge_size_y); + gdk_flush(); +} + +void lingot_mainframe_draw_spectrum(LingotMainFrame* frame) { + PangoLayout* layout; + + int + spectrum_size_x = + ((frame->conf->fft_size > 256) ? (frame->conf->fft_size + >> 1) : 256); + + // minimum grid size in pixels + static int minimum_grid_width = 50; + + /* scale factors to draw the grid. We will choose the smaller factor that + respects the minimum_grid_width */ + static double + scales[] = { 0.01, 0.05, 0.1, 0.2, 0.5, 1, 2, 4, 11, 22, -1.0 }; + + // spectrum drawing mode + static gboolean spectrum_drawing_filled = TRUE; + + // grid division in dB + static FLT grid_db_height = 25; + + register unsigned int i; + int j; + int old_j; + + GdkGC* gc = frame->spectrum_area->style->fg_gc[frame->spectrum_area->state]; + GdkWindow* window = frame->pix_spectrum; //spectrum->window; + GdkGCValues gv; + gdk_gc_get_values(gc, &gv); + + // clear all + gdk_gc_set_foreground(gc, &spectrum_background_color); + gdk_draw_rectangle(window, gc, TRUE, 0, 0, spectrum_size_x + 2 + *spectrum_x_margin, spectrum_size_y + spectrum_bottom_margin + + spectrum_top_margin); + + gdk_gc_set_foreground(gc, &grid_color); + + gdk_draw_line(window, gc, spectrum_x_margin, spectrum_size_y + + spectrum_top_margin, spectrum_x_margin + spectrum_size_x, + spectrum_size_y + spectrum_top_margin); + + // choose scale factor + for (i = 0; scales[i] > 0.0; i++) { + if ((1e3*scales[i]*frame->conf->fft_size*frame->conf->oversampling + /frame->conf->sample_rate) > minimum_grid_width) + break; + } + + if (scales[i] < 0.0) + i--; + + FLT scale = scales[i]; + + int grid_width = 1e3*scales[i]*frame->conf->fft_size + *frame->conf->oversampling/frame->conf->sample_rate; + + char buff[10]; + + FLT freq = 0.0; + for (i = 0; i <= spectrum_size_x; i += grid_width) { + gdk_draw_line(window, gc, spectrum_x_margin + i, spectrum_top_margin, + spectrum_x_margin + i, spectrum_size_y + spectrum_top_margin + + 3); + + if (freq == 0.0) { + sprintf(buff, "0 Hz"); + } else if (floor(freq) == freq) + sprintf(buff, "%0.0f kHz", freq); + else if (floor(10*freq) == 10*freq) { + if (freq <= 1000.0) + sprintf(buff, "%0.0f Hz", 1e3*freq); + else + sprintf(buff, "%0.1f kHz", freq); + } else { + if (freq <= 100.0) + sprintf(buff, "%0.0f Hz", 1e3*freq); + else + sprintf(buff, "%0.2f kHz", freq); + } + + layout = gtk_widget_create_pango_layout(frame->spectrum_area, buff); + pango_layout_set_font_description(layout, spectrum_legend_font_desc); + gdk_draw_layout(window, gc, spectrum_x_margin - 8 + i, spectrum_size_y + + spectrum_top_margin + 5, layout); + freq += scale; + } + +# define PLOT_GAIN 8 + + sprintf(buff, "dB"); + + layout = gtk_widget_create_pango_layout(frame->spectrum_area, buff); + pango_layout_set_font_description(layout, spectrum_legend_font_desc); + gdk_draw_layout(window, gc, spectrum_x_margin - 6, 2, layout); + + int grid_height = (int) (PLOT_GAIN*log10(pow(10.0, grid_db_height/10.0))); // dB. + j = 0; + for (i = 0; i <= spectrum_size_y; i += grid_height) { + if (j == 0) + sprintf(buff, " %i", j); + else + sprintf(buff, "%i", j); + + layout = gtk_widget_create_pango_layout(frame->spectrum_area, buff); + pango_layout_set_font_description(layout, spectrum_legend_font_desc); + gdk_draw_layout(window, gc, 2, spectrum_size_y + spectrum_top_margin + - i - 5, layout); + + gdk_draw_line(window, gc, spectrum_x_margin, spectrum_size_y + + spectrum_top_margin - i, spectrum_x_margin + spectrum_size_x, + spectrum_size_y + spectrum_top_margin - i); + + j += grid_db_height; + } + + gdk_gc_set_foreground(gc, &noise_threshold_color); + + // noise threshold drawing. + j = -1; + for (i = 0; (i < frame->conf->fft_size) && (i < spectrum_size_x); i++) { + if ((i % 10) > 5) + continue; + + FLT w = 2*M_PI*i/frame->conf->fft_size; + //FLT noise = pow(10.0, (frame->conf->noise_threshold_db*(1.0 - 0.9*w/M_PI))/10.0); + //FLT noise = lingot_signal_get_noise_threshold(frame->conf, w); + FLT noise = frame->conf->noise_threshold_nu; + old_j = j; + j = (noise > 1.0) ? (int) (PLOT_GAIN*log10(noise)) : 0; // dB. + if ((old_j >= 0) && (old_j < spectrum_size_y)&& (j >= 0)&& (j + < spectrum_size_y)) + gdk_draw_line(window, gc, spectrum_x_margin + i - 1, + spectrum_size_y + spectrum_top_margin - old_j, + spectrum_x_margin + i, spectrum_size_y + + spectrum_top_margin - j); + } + + gdk_gc_set_foreground(gc, &spectrum_color); + + // spectrum drawing. + j = -1; + for (i = 0; (i < frame->conf->fft_size - 1) && (i < spectrum_size_x - 1); i++) { + old_j = j; + j = (frame->core->X[i] > 1.0) ? (int) (PLOT_GAIN*log10(frame->core->X[i])) : 0; // dB. + if (spectrum_drawing_filled) { + if (j < spectrum_size_y) + gdk_draw_line(window, gc, spectrum_x_margin + i, + spectrum_size_y + spectrum_top_margin - 1, + spectrum_x_margin + i, spectrum_top_margin + ((j + < spectrum_size_y) ? (spectrum_size_y - j) : 0)); + } else if ((old_j >= 0) && (old_j < spectrum_size_y)&& (j >= 0)&& (j + < spectrum_size_y)) + gdk_draw_line(window, gc, spectrum_x_margin + i - 1, + spectrum_size_y + spectrum_top_margin - old_j, + spectrum_x_margin + i, spectrum_size_y + + spectrum_top_margin - j); + } + + if (frame->core->freq != 0.0) { + + // fundamental frequency mark with a red point. + gdk_gc_set_foreground(gc, &freq_color); + + // index of closest sample to fundamental frequency. + i = (int) rint(frame->core->freq*frame->conf->fft_size + *frame->conf->oversampling/frame->conf->sample_rate); + if ((i < frame->conf->fft_size - 1) && (i < spectrum_size_x - 1)) { + j = (frame->core->X[i] > 1.0) ? (int) (PLOT_GAIN*log10(frame->core->X[i])) : 0; // dB. + if (j < spectrum_size_y - 1) + gdk_draw_rectangle(window, gc, TRUE, spectrum_x_margin + i-1, + spectrum_size_y + spectrum_top_margin - j - 1, 3, 3); + } + } + +# undef PLOT_GAIN + + gdk_gc_set_foreground(gc, &black_color); + + gdk_draw_pixmap(frame->spectrum_area->window, gc, window, 0, 0, 0, 0, + spectrum_size_x + 2*spectrum_x_margin, spectrum_size_y + + spectrum_bottom_margin + spectrum_top_margin); + gdk_flush(); +} + +void lingot_mainframe_put_frequency(LingotMainFrame* frame) { + // note indexation by semitone. + static char* note_string[] = { "A", "A#", "B", "C", "C#", "D", "D#", "E", + "F", "F#", "G", "G#" }; + const FLT Log2 = log(2.0); + + FLT fret_f; + int fret; + char* current_note; + char labeltext_current_note[100]; + + static char error_string[30], freq_string[30]; + + LingotCore* core1 = frame->core; + + // ignore continuous component + if (isnan(frame->core->freq) || (frame->core->freq < 10.0)) { + current_note = "---"; + strcpy(error_string, "e = ---"); + strcpy(freq_string, "f = ---"); + lingot_gauge_compute(frame->gauge, frame->conf->vr); + } else { + // bring up some octaves to avoid negative frets. + fret_f = log(frame->core->freq/frame->conf->root_frequency)/Log2*12.0 + + 12e2; + + lingot_gauge_compute(frame->gauge, fret_f - rint(fret_f)); + fret = ((int) rint(fret_f)) % 12; + + current_note = note_string[fret]; + sprintf(error_string, "e = %+4.2f%%", frame->gauge->position*100.0); + sprintf(freq_string, "f = %6.2f Hz", lingot_filter_filter_sample( + frame->freq_filter, frame->core->freq)); + } + + gtk_label_set_text(GTK_LABEL(frame->freq_label), freq_string); + gtk_label_set_text(GTK_LABEL(frame->error_label), error_string); + + char* markup = g_markup_printf_escaped( + "<span size=\"xx-large\" weight=\"bold\">%s</span>", current_note); + gtk_label_set_markup(GTK_LABEL(frame->note_label), markup); + g_free(markup); +} + +void lingot_mainframe_change_config(LingotMainFrame* frame, LingotConfig* conf) { + lingot_core_stop(frame->core); + lingot_core_destroy(frame->core); + + // dup. + *frame->conf = *conf; + + // resize spectrum area + g_object_unref(frame->pix_spectrum); + + int + x = ((frame->conf->fft_size > 256) ? (frame->conf->fft_size >> 1) + : 256) + 2*spectrum_x_margin; + int y = spectrum_size_y + spectrum_top_margin + spectrum_bottom_margin; + gtk_widget_set_size_request(GTK_WIDGET(frame->spectrum_area), x, y); + frame->pix_spectrum= gdk_pixmap_new(frame->spectrum_area->window, x, y, -1); + + gtk_scrolled_window_set_policy(frame->spectrum_scroll, + (frame->conf->fft_size > 512) ? GTK_POLICY_ALWAYS + : GTK_POLICY_NEVER, GTK_POLICY_NEVER); + gtk_widget_set_size_request(GTK_WIDGET(frame->spectrum_scroll), 260 + 2 + *spectrum_x_margin, spectrum_size_y + spectrum_bottom_margin + + spectrum_top_margin + 4 + + ((frame->conf->fft_size > 512) ? 16 : 0)); + + frame->core = lingot_core_new(frame->conf); + lingot_core_start(frame->core); +} diff --git a/src/lingot-mainframe.h b/src/lingot-mainframe.h new file mode 100644 index 0000000..8e4dd08 --- /dev/null +++ b/src/lingot-mainframe.h @@ -0,0 +1,82 @@ +//-*- C++ -*- +/* + * lingot, a musical instrument tuner. + * + * Copyright (C) 2004-2007 Ibán Cereijo Graña, Jairo Chapela Martínez. + * + * This file is part of lingot. + * + * lingot 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. + * + * lingot 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 lingot; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LINGOT_MAIN_FRAME_H__ +#define __LINGOT_MAIN_FRAME_H__ + +#include "lingot-defs.h" +#include "lingot-core.h" +#include "lingot-gauge.h" +#include "lingot-config.h" +#include "lingot-config-dialog.h" +#include "lingot-filter.h" + +#include <gtk/gtk.h> + +// Window that contains all controls, graphics, etc. of the tuner. + +//typedef struct _LingotMainFrame LingotMainFrame; + +struct _LingotMainFrame + { + + // gtk widgets + GtkWidget* gauge_area; + GtkWidget* spectrum_area; + GtkWidget* note_label; + + GtkWidget* freq_label; + GtkWidget* error_label; + + GdkPixmap* pix_spectrum; + GdkPixmap* pix_stick; + + GtkScrolledWindow* spectrum_scroll; + + LingotFilter* freq_filter; + + LingotGauge* gauge; + + LingotCore* core; + + GtkWidget* win; + + GdkColor gauge_color; + GdkColor spectrum_color; + + LingotConfigDialog* config_dialog; + LingotConfig* conf; + + // timer uids + guint visualization_timer_uid; + guint calculation_timer_uid; + guint freq_timer_uid; + }; + +LingotMainFrame* lingot_mainframe_new(int argc, char *argv[]); +void lingot_mainframe_destroy(LingotMainFrame*); + +void lingot_mainframe_run(LingotMainFrame*); +void lingot_mainframe_change_config(LingotMainFrame*, LingotConfig*); + +#endif //__LINGOT_MAIN_FRAME_H__ diff --git a/src/lingot-signal.c b/src/lingot-signal.c new file mode 100644 index 0000000..e675216 --- /dev/null +++ b/src/lingot-signal.c @@ -0,0 +1,153 @@ +//-*- C++ -*- +/* + * lingot, a musical instrument tuner. + * + * Copyright (C) 2004-2007 Ibán Cereijo Graña, Jairo Chapela Martínez. + * + * This file is part of lingot. + * + * lingot 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. + * + * lingot 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 lingot; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <math.h> + +#include "lingot-signal.h" + +/* + peak identification functions. + */ + +FLT lingot_signal_get_noise_threshold(LingotConfig* conf, FLT w) +{ + //return 0.5*(1.0 - 0.9*w/M_PI); + return pow(10.0, (conf->noise_threshold_db*(1.0 - 0.9*w/M_PI))/10.0); + //return conf->noise_threshold_un; +} + +//--------------------------------------------------------------------------- + +/* returns the index of the maximun of the buffer x of size N */ +void lingot_signal_get_max(FLT *x, int N, int* Mi) { + register int i; + FLT M; + + M = -1.0; + *Mi = -1; + + for (i = 0; i < N; i++) { + + if (x[i] > M) { + M = x[i]; + *Mi = i; + } + } +} + +//--------------------------------------------------------------------------- + +int lingot_signal_is_peak(LingotConfig* conf, FLT* x, int index) { + register unsigned int j; + //static FLT delta_w_FFT = 2.0*M_PI/conf->FFT_SIZE; // resolution in rads + + // a peak must be greater than noise threshold. + if (x[index] < conf->noise_threshold_nu) + return 0; + + for (j = 0; j < conf->peak_order; j++) { + if (x[index + j] < x[index + j + 1]) + return 0; + if (x[index - j] < x[index - j - 1]) + return 0; + } + return 1; +} + +//--------------------------------------------------------------------------- + +// search the fundamental peak given the spd and its 2nd derivative +int lingot_signal_get_fundamental_peak(LingotConfig* conf, FLT *x, FLT* d2x, + int N) { + register unsigned int i, j, m; + int p_index[conf->peak_number]; + + // at this moment there is no peaks. + for (i = 0; i < conf->peak_number; i++) + p_index[i] = -1; + + unsigned int lowest_index = (unsigned int)ceil(conf->min_frequency*(1.0 + *conf->oversampling/conf->sample_rate)*conf->fft_size); + + if (lowest_index < conf->peak_order) + lowest_index = conf->peak_order; + + // I'll get the PEAK_NUMBER maximum peaks. + for (i = lowest_index; i < N - conf->peak_order; i++) + if (lingot_signal_is_peak(conf, x, i)) { + + // search a place in the maximums buffer, if it doesn't exists, the + // lower maximum is candidate to be replaced. + m = 0; // first candidate. + for (j = 0; j < conf->peak_number; j++) { + if (p_index[j] == -1) { + m = j; // there is a place. + break; + } + + if (d2x[p_index[j]] < d2x[p_index[m]]) + m = j; // search the lowest. + } + + if (p_index[m] == -1) + p_index[m] = i; // there is a place + else if (d2x[i] > d2x[p_index[m]]) + p_index[m] = i; // if greater + } + + FLT maximum = 0.0; + int maximum_index = -1; + + // search the maximum peak + for (i = 0; i < conf->peak_number; i++) + if ((p_index[i] != -1) && (x[p_index[i]] > maximum)) { + maximum = x[p_index[i]]; + maximum_index = p_index[i]; + } + + if (maximum_index == -1) + return N; + + // all peaks much lower than maximum are deleted. + for (i = 0; i < conf->peak_number; i++) + if ((p_index[i] == -1) ||(conf->peak_rejection_relation_nu + *x[p_index[i]] < maximum)) + p_index[i] = N; // there are available places in the buffer. + + // search the lowest maximum index. + for (m = 0, j = 0; j < conf->peak_number; j++) { + if (p_index[j] < p_index[m]) + m = j; + } + + return p_index[m]; +} + +//--------------------------------------------------------------------------- + +// generates a Hamming window of N samples +void lingot_signal_hamming_window(int N, FLT* out) { + register int i; + for (i = 0; i < N; i++) + out[i] = 0.53836 - 0.46164*cos((2.0*M_PI*i)/(N-1)); +} diff --git a/src/lingot-signal.h b/src/lingot-signal.h new file mode 100644 index 0000000..7092f92 --- /dev/null +++ b/src/lingot-signal.h @@ -0,0 +1,49 @@ +//-*- C++ -*- +/* + * lingot, a musical instrument tuner. + * + * Copyright (C) 2004-2007 Ibán Cereijo Graña, Jairo Chapela Martínez. + * + * This file is part of lingot. + * + * lingot 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. + * + * lingot 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 lingot; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LINGOT_SIGNAL_H__ +#define __LINGOT_SIGNAL_H__ + +/* + peak identification functions. + */ + +#include "lingot-defs.h" +#include "lingot-config.h" + +// returns noise threshold at a given frequency w. +FLT lingot_signal_get_noise_threshold(LingotConfig*, FLT w); + +// returns if buffer has a peak at given index +int lingot_signal_is_peak(LingotConfig*, FLT* buffer, int index); + +// returns the maximum index. +void lingot_signal_get_max(FLT *buffer, int N, int* Mi); + +// returns the index of the peak that carries the fundamental freq. +int lingot_signal_get_fundamental_peak(LingotConfig*, FLT *x, FLT* y, int N); + +// generates a Hamming window of N samples +void lingot_signal_hamming_window(int N, FLT* out); + +#endif /*__LINGOT_SIGNAL_H__*/ diff --git a/src/lingot.c b/src/lingot.c new file mode 100644 index 0000000..4da9f53 --- /dev/null +++ b/src/lingot.c @@ -0,0 +1,132 @@ +//-*- C++ -*- +/* + * lingot, a musical instrument tuner. + * + * Copyright (C) 2004-2007 Ibán Cereijo Graña, Jairo Chapela Martínez. + * + * This file is part of lingot. + * + * lingot 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. + * + * lingot 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 lingot; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <fcntl.h> +#include <unistd.h> +#include <getopt.h> + +#include "lingot-defs.h" +#include "lingot-config.h" +#include "lingot-mainframe.h" +#include "lingot-i18n.h" + +char CONFIG_FILE_NAME[100]; + +int main(int argc, char *argv[]) + { + +#ifdef ENABLE_NLS + bindtextdomain (GETTEXT_PACKAGE, LINGOT_LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); +#endif + + // default config file. + sprintf(CONFIG_FILE_NAME, "%s/" CONFIG_DIR_NAME DEFAULT_CONFIG_FILE_NAME, + getenv("HOME")); + + // TODO: indicate complete config file path + if ((argc > 3) || (argc == 2)) + { + printf("\nusage: lingot [-c config]\n\n"); + return -1; + } + else if (argc > 1) + { + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = + { + { "config", 1, 0, 'c'}, + { 0, 0, 0, 0} + }; + + c = getopt_long (argc, argv, "c:", + long_options, &option_index); + if (c == -1) + break; + + switch (c) + { + case 'c': + sprintf(CONFIG_FILE_NAME, "%s/%s%s.conf", getenv("HOME"), + CONFIG_DIR_NAME, optarg); + printf("using config file %s\n", CONFIG_FILE_NAME); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + /* if (strcmp(argv[1], "-c") || (argc < 3)) + { + printf("invalid argument\n"); + return -1; + } + + sprintf(CONFIG_FILE_NAME, "%s/%s%s.conf", getenv("HOME"), + CONFIG_DIR_NAME, argv[2]); + printf("using config file %s\n", CONFIG_FILE_NAME);*/ + } + + // if config file doesn't exists, i will create it. + FILE* fp; + if ((fp = fopen(CONFIG_FILE_NAME, "r")) == NULL) + { + + char config_dir[100]; + sprintf(config_dir, "%s/.lingot/", getenv("HOME")); + printf("creating directory %s ...\n", config_dir); + mkdir(config_dir, 0777); // creo el directorio. + printf("creating file %s ...\n", CONFIG_FILE_NAME); + + // new configuration with default values. + LingotConfig* new_conf = lingot_config_new(); + lingot_config_save(new_conf, CONFIG_FILE_NAME); + lingot_config_destroy(new_conf); + + printf("ok\n"); + + } + else + fclose(fp); + + LingotMainFrame* gui = lingot_mainframe_new(argc, argv); + lingot_mainframe_run(gui); + + return 0; + } |
