├── AUTHORS ├── CHANGES ├── COPYING ├── COPYING.artistic ├── INSTALL ├── Makefile.am ├── README ├── README.timidity ├── TODO ├── autotools ├── config.guess └── config.sub ├── configure.ac ├── libtimidity.pc.in ├── libtimidity.spec.in ├── m4 └── ao.m4 ├── src ├── Makefile.am ├── Makefile.amigaos ├── Makefile.aros ├── Makefile.darwin ├── Makefile.dj ├── Makefile.emx ├── Makefile.mingw ├── Makefile.morphos ├── Makefile.os2 ├── Makefile.vbcc ├── Makefile.w32 ├── VS2005 │ ├── libtimidity.sln │ ├── libtimidity.vcproj │ └── timidity_static.vcproj ├── VisualStudio │ ├── libtimidity.sln │ ├── libtimidity.vcxproj │ ├── libtimidity.vcxproj.filters │ ├── timidity_static.vcxproj │ └── timidity_static.vcxproj.filters ├── XCode │ ├── Info.plist │ ├── InfoPlist.strings │ ├── libtimidity.exports │ └── libtimidity.xcodeproj │ │ └── project.pbxproj ├── common.c ├── common.h ├── instrum.c ├── instrum.h ├── mix.c ├── mix.h ├── options.h ├── ospaths.h ├── output.c ├── output.h ├── playmidi.c ├── playmidi.h ├── readmidi.c ├── readmidi.h ├── resample.c ├── resample.h ├── stream.c ├── tables.c ├── tables.h ├── timi_endian.h ├── timidity.c ├── timidity.h └── timidity_internal.h └── tests ├── Makefile.am ├── ame002.mid ├── midi2raw.c ├── playmidi.c └── runtest.sh /AUTHORS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sezero/libtimidity/61bfd3ad9c42561ffe4552b426c0c79514754525/AUTHORS -------------------------------------------------------------------------------- /CHANGES: -------------------------------------------------------------------------------- 1 | Changes by libtimidity-0.2.7: 2 | ----------------------------- 3 | 4 | - Several code clean-ups. 5 | - Several build and portability fixes/updates. Removed support for 6 | lcc-win32 compiler. 7 | 8 | 9 | Changes by libtimidity-0.2.6: 10 | ----------------------------- 11 | 12 | * fixed a possibly signed integer overflow with crafted midi files. 13 | * other minor clean-ups, etc. 14 | 15 | 16 | Changes by libtimidity-0.2.5: 17 | ----------------------------- 18 | 19 | * allow dual-licensing as LGPL / Artistic. 20 | 21 | 22 | Changes by libtimidity-0.2.4: 23 | ----------------------------- 24 | 25 | * fixes to the pkg-config file. 26 | 27 | 28 | Changes by libtimidity-0.2.3: 29 | ----------------------------- 30 | 31 | * fixed a potential buffer overrun in timi_fgets() which might have led 32 | to a crash during config parsing. 33 | 34 | 35 | Changes by libtimidity-0.2.2: 36 | ----------------------------- 37 | 38 | * removed DLS instruments support completely, it was never good enough: 39 | one less thing to worry about. and no, the 0.2.x api didn't change. 40 | 41 | 42 | Changes by libtimidity-0.2.1: 43 | ----------------------------- 44 | 45 | * new --with-timidty-cfg=FILE configury option to specify the full path 46 | of timidity.cfg. the default is "timidity.cfg". if building without 47 | configury and a config.h, you can always edit options.h to change the 48 | value of TIMITIDY_CFG macro. 49 | * fixed 8 bit output in test programs (use U8 format, not S8), along 50 | with some other minor issues. 51 | * fixed some minor portability issues. 52 | * added project files and standalone makefiles for windows and mac os x. 53 | * fixed copyright/license mistakes in some files, license clarification. 54 | * added standalone makefiles for less common operating systems e.g. dos, 55 | os/2, morphos, aros, and amigaos. 56 | 57 | 58 | Changes by libtimidity-0.2.0: 59 | ----------------------------- 60 | 61 | * stream.c, api change: added mid_istream_seek and mid_istream_tell to 62 | the mid_istream_* api. added seek and tell funcs to the _MidIStream 63 | structure. mid_istream_open_callbacks() is changed now accepts these 64 | callbacks. 65 | 66 | * stream.c, api change: mid_istream_open_mem() no longer accepts an 67 | autoclose parameter, which was error-prone. 68 | 69 | * MidSongOptions, api change: padded the struct with reserved members 70 | for better alignment. 71 | 72 | * mid_song_load(): options are now validated. limited the acceptable 73 | sample rate range to 4000-256000. MID_AUDIO_U16MSB audio format is 74 | now handled correctly. 75 | 76 | * malloc-safe: upon memory allocation failures, the library either does 77 | a mid_exit() to free all the allocated memory during init time, or a 78 | mid_song_free() to free the allocated memory during a song load time. 79 | 80 | * the library can be compiled using a different memory allocator than 81 | malloc. (edit common.h for timi_malloc and timi_free) 82 | 83 | * mid_init(), mid_init_no_config(): a mid_exit() is guaranteed upon 84 | config file parse failures or malloc() failures. 85 | 86 | * mid_init(): the library doesn't care about common timidity.cfg system 87 | locations any more, callers of mid_init() are responsible for it. if 88 | the config file argument to mid_init() contains a parent directory, 89 | that will be added to timidity search path. 90 | 91 | * mid_exit(): does a proper cleanup now and a reinitialization of the 92 | library doesn't crash. 93 | 94 | * multiple resampling fixes. several timidity-0.2i fixes from the 95 | onicos.com site (http://www.onicos.com/staff/iz/timidity/dist/), 96 | as well as a few bits from timidity++. several fixes for memory 97 | errors reported by valgrind. 98 | 99 | * mid_istream_skip(): accepts a long type length instead of size_t 100 | and returns success or failure now. 101 | 102 | * options.h (DEFAULT_DRUMCHANNELS): do not mark 16 as a drum channel. 103 | 104 | * read_midi_file(): added support for Microsoft RMID format. 105 | 106 | * read_midi_file(): fixed parsing of certain MIDI files with extra 107 | data at the end of the tracks. (SDL_mixer bug: 108 | http://bugzilla.libsdl.org/show_bug.cgi?id=1299) 109 | 110 | * read_config_file(): honor the return code from a recursive call. 111 | 112 | * mid_get_version(): new function to retrieve library version. 113 | 114 | * DLS instruments support: made it a config time option, disabled by 115 | default, because the code isn't good enough, neither is it used in 116 | unix installations where timidity is normally needed. 117 | 118 | * DLS: a few changes from vavoom svn repository to fix loading of drums 119 | and somewhat improve the dls instruments use. still not good enough. 120 | 121 | * renamed macro FSCALE to TIM_FSCALE to avoid possible clashes with 122 | system headers. renamed FSCALENEG to TIM_FSCALENEG for consistency. 123 | 124 | * support for elf and macho symbol visibility attributes. support for 125 | windows dllexport/dllimport attributes. 126 | 127 | * build: changed DEBUG to TIMIDITY_DEBUG for DEBUG_MSG. made to compile 128 | cleanly using newer gcc versions, as well as clang. made it to compile 129 | using C++ compilers. 130 | 131 | ------------------------------------------------------------------------ 132 | 133 | Changes by libtimidity-0.1.0: 134 | ----------------------------- 135 | 136 | This version of TiMidity should contain all the fixes from the 137 | November 15 2004 SDL_sound Subversion snapshot. In addition, I've made some 138 | changes of my own, e.g.: 139 | 140 | * Replacing SDL types and endian-handling with owns. 141 | 142 | * File access to the config file and instruments is done through 143 | stdio functions. File access to MIDI files is done through abstract 144 | input stream. Implemented functions to create input stream from 145 | file name, from stdio file pointer, from memory, from callback functions. 146 | 147 | * Renamed interface functions 148 | Timidity_Init -> mid_init 149 | Timidity_Init_NoConfig -> mid_init_no_config 150 | Timidity_SetVolume -> mid_song_set_volume 151 | Timidity_PlaySome -> mid_song_read_wave 152 | Timidity_LoadDLS -> mid_dlspatches_load 153 | Timidity_FreeDLS -> mid_dlspatches_free 154 | Timidity_LoadDLSSong -> mid_song_load_dls 155 | Timidity_LoadSong -> mid_song_load 156 | Timidity_Start -> mid_song_start 157 | Timidity_Seek -> mid_song_seek 158 | Timidity_GetSongLength -> mid_song_get_total_time 159 | Timidity_FreeSong -> mid_song_free 160 | 161 | * Most structures and macro definition made hidden and placed in 162 | timidity_internal.h. 163 | 164 | * Results of mid_song_read_wave (Timidity_PlaySome) not 165 | depends with internal sample buffer size. 166 | 167 | * mid_init can accept timidity config file name. 168 | 169 | * Added functions: mid_song_get_time, mid_song_get_meta. 170 | 171 | * Added examples/tests midi2raw.c and playmidi.c. 172 | 173 | -- 174 | Konstantin Korikov 175 | 176 | ------------------------------------------------------------------------ 177 | 178 | Changes by SDL_sound-1.0.1: 179 | --------------------------- 180 | 181 | This version of TiMidity should contain all the fixes from the 182 | September 25 2003 SDL_mixer CVS snapshot. In addition, I've made some 183 | changes of my own, e.g.: 184 | 185 | * All file access is done through SDL_RWops. This means the MIDI 186 | stream no longer has to be a file. (The config file and instruments 187 | still have to be though.) 188 | 189 | * Replacing of TiMidity's endian-handling with SDL's. 190 | 191 | * Removal of much unused or unnecessary code, such as 192 | 193 | + The "hooks" for putting a user interface onto TiMidity. 194 | + The antialias filter. It wasn't active, and even at 4 kHz I 195 | couldn't hear any difference when activating it. 196 | + Removed all traces of LOOKUP_HACK and LOOKUP_INTERPOLATION. 197 | According to the code comments they weren't very good anyway. 198 | ("degrades sound quality noticeably"). I also removed the 199 | disclaimer about the "8-bit uLaw to 16-bit PCM and the 13-bit-PCM 200 | to 8-bit uLaw tables" disclaimer, since I believe those were the 201 | tables I removed. 202 | + Removed LOOKUP_SINE since it was already commented out. I think we 203 | can count on our target audience having math co-processors 204 | nowadays. 205 | + Removed USE_LDEXP since it wasn't being used and "it doesn't make 206 | much of a difference either way". 207 | + Removed decompress hack from open_file() since it didn't look very 208 | portable. 209 | + Removed heaps of unnecessary constants. 210 | + Removed unused functions. 211 | + Assume that LINEAR_INTERPOLATION is always used, so remove all 212 | code dealing with it not being so. It's not that I think the 213 | difference in audio quality is that great, but since it wouldn't 214 | compile without code changes I assume no one's used it for quite 215 | some time... 216 | + Assume PRECALC_LOOPS is always defined. Judging by the comments it 217 | may not make much of a difference either way, so why maintain two 218 | versions of the same code? 219 | 220 | * Moving several static globals into the MidiSong struct. This 221 | includes sample rate, formate, etc. which are now all per-song. 222 | 223 | * Moved some typedefs (e.g. MidiSong) to timidity.h for easy inclusion 224 | into the MIDI decoder. 225 | 226 | * Added free_pathlist(). 227 | 228 | * Replaced TiMidity's own 8, 16 and 32-bit types with SDL's. 229 | 230 | * Made TiMidity look for its configuration file in both /etc and 231 | /usr/local/lib/timidity. (Windows version remains unchanged.) 232 | 233 | * Timidity_PlaySome() now takes three arguments. A MidiSong, a decode 234 | buffer and decode buffer size in bytes. (MidiSong is a new argument, 235 | and buffer size used to be in samples.) 236 | 237 | In addition, it will return the number of bytes decoded. 238 | 239 | * Added Timidity_Exit(). 240 | 241 | * Removed Timidity_Stop() and Timidity_Active(). Stopping playback 242 | should be handled by SDL_sound, and Timidity_PlaySome() will return 243 | 0 when the MIDI stream is finished. 244 | 245 | * Modified the ToneBank stuff to allow some data to be shared between 246 | MidiSongs. 247 | 248 | * The following files have been removed: controls.c, controls.h, 249 | filter.c, filter.h, sdl_a.c, sdl_c.c 250 | 251 | * config.h has been renamed as options.h to avoid confusion with the 252 | automatically generated config.h for SDL_sound. 253 | 254 | * Added support for loading DLS format instruments: 255 | Timidity_LoadDLS(), Timidity_FreeDLS(), Timidity_LoadDLSSong() 256 | 257 | * Added Timidity_Init_NoConfig() 258 | 259 | -------------------------------------------------------------------------------- /COPYING.artistic: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | The "Artistic License" 6 | 7 | Preamble 8 | 9 | The intent of this document is to state the conditions under which a 10 | Package may be copied, such that the Copyright Holder maintains some 11 | semblance of artistic control over the development of the package, 12 | while giving the users of the package the right to use and distribute 13 | the Package in a more-or-less customary fashion, plus the right to make 14 | reasonable modifications. 15 | 16 | Definitions: 17 | 18 | "Package" refers to the collection of files distributed by the 19 | Copyright Holder, and derivatives of that collection of files 20 | created through textual modification. 21 | 22 | "Standard Version" refers to such a Package if it has not been 23 | modified, or has been modified in accordance with the wishes 24 | of the Copyright Holder as specified below. 25 | 26 | "Copyright Holder" is whoever is named in the copyright or 27 | copyrights for the package. 28 | 29 | "You" is you, if you're thinking about copying or distributing 30 | this Package. 31 | 32 | "Reasonable copying fee" is whatever you can justify on the 33 | basis of media cost, duplication charges, time of people involved, 34 | and so on. (You will not be required to justify it to the 35 | Copyright Holder, but only to the computing community at large 36 | as a market that must bear the fee.) 37 | 38 | "Freely Available" means that no fee is charged for the item 39 | itself, though there may be fees involved in handling the item. 40 | It also means that recipients of the item may redistribute it 41 | under the same conditions they received it. 42 | 43 | 1. You may make and give away verbatim copies of the source form of the 44 | Standard Version of this Package without restriction, provided that you 45 | duplicate all of the original copyright notices and associated disclaimers. 46 | 47 | 2. You may apply bug fixes, portability fixes and other modifications 48 | derived from the Public Domain or from the Copyright Holder. A Package 49 | modified in such a way shall still be considered the Standard Version. 50 | 51 | 3. You may otherwise modify your copy of this Package in any way, provided 52 | that you insert a prominent notice in each changed file stating how and 53 | when you changed that file, and provided that you do at least ONE of the 54 | following: 55 | 56 | a) place your modifications in the Public Domain or otherwise make them 57 | Freely Available, such as by posting said modifications to Usenet or 58 | an equivalent medium, or placing the modifications on a major archive 59 | site such as uunet.uu.net, or by allowing the Copyright Holder to include 60 | your modifications in the Standard Version of the Package. 61 | 62 | b) use the modified Package only within your corporation or organization. 63 | 64 | c) rename any non-standard executables so the names do not conflict 65 | with standard executables, which must also be provided, and provide 66 | a separate manual page for each non-standard executable that clearly 67 | documents how it differs from the Standard Version. 68 | 69 | d) make other distribution arrangements with the Copyright Holder. 70 | 71 | 4. You may distribute the programs of this Package in object code or 72 | executable form, provided that you do at least ONE of the following: 73 | 74 | a) distribute a Standard Version of the executables and library files, 75 | together with instructions (in the manual page or equivalent) on where 76 | to get the Standard Version. 77 | 78 | b) accompany the distribution with the machine-readable source of 79 | the Package with your modifications. 80 | 81 | c) give non-standard executables non-standard names, and clearly 82 | document the differences in manual pages (or equivalent), together 83 | with instructions on where to get the Standard Version. 84 | 85 | d) make other distribution arrangements with the Copyright Holder. 86 | 87 | 5. You may charge a reasonable copying fee for any distribution of this 88 | Package. You may charge any fee you choose for support of this 89 | Package. You may not charge a fee for this Package itself. However, 90 | you may distribute this Package in aggregate with other (possibly 91 | commercial) programs as part of a larger (possibly commercial) software 92 | distribution provided that you do not advertise this Package as a 93 | product of your own. You may embed this Package's interpreter within 94 | an executable of yours (by linking); this shall be construed as a mere 95 | form of aggregation, provided that the complete Standard Version of the 96 | interpreter is so embedded. 97 | 98 | 6. The scripts and library files supplied as input to or produced as 99 | output from the programs of this Package do not automatically fall 100 | under the copyright of this Package, but belong to whoever generated 101 | them, and may be sold commercially, and may be aggregated with this 102 | Package. If such scripts or library files are aggregated with this 103 | Package via the so-called "undump" or "unexec" methods of producing a 104 | binary executable image, then distribution of such an image shall 105 | neither be construed as a distribution of this Package nor shall it 106 | fall under the restrictions of Paragraphs 3 and 4, provided that you do 107 | not represent such an executable image as a Standard Version of this 108 | Package. 109 | 110 | 7. C subroutines (or comparably compiled subroutines in other 111 | languages) supplied by you and linked into this Package in order to 112 | emulate subroutines and variables of the language defined by this 113 | Package shall not be considered part of this Package, but are the 114 | equivalent of input as in Paragraph 6, provided these subroutines do 115 | not change the language in any way that would cause it to fail the 116 | regression tests for the language. 117 | 118 | 8. Aggregation of this Package with a commercial distribution is always 119 | permitted provided that the use of this Package is embedded; that is, 120 | when no overt attempt is made to make this Package's interfaces visible 121 | to the end user of the commercial distribution. Such use shall not be 122 | construed as a distribution of this Package. 123 | 124 | 9. The name of the Copyright Holder may not be used to endorse or promote 125 | products derived from this software without specific prior written permission. 126 | 127 | 10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR 128 | IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 129 | WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 130 | 131 | The End 132 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | INSTALL file for libtimidity 2 | ============================ 3 | 4 | In most systems just run: 5 | $ ./configure 6 | $ make 7 | 8 | You need GNU make. On BSD or SysV systems, you may need to use gmake 9 | instead of make. Use ./configure --help to see configuration options. 10 | Hint: You may want to use --with-timidty-cfg=/path/to/timidity.cfg . 11 | To install the library and development components, run "make install" 12 | as the superuser. This will install the shared and static libraries, 13 | header file and pkg-config file into directories under /usr/local or a 14 | different location selected with the --prefix option in configure. 15 | 16 | To cross-compile, you will need to use the --host option of configury. 17 | For example: 18 | $ ./configure --host=powerpc-apple-darwin9 # for Mac OS X (powerpc) 19 | $ ./configure --host=i686-pc-mingw32 # for Windows (win32) 20 | $ ./configure --host=x86_64-w64-mingw32 # for Windows (win64) 21 | 22 | For Mac OS X, we provide an XCode project file for your convinence. 23 | 24 | For Windows, we provide a Visual Studio project file (for VS2005 or 25 | newer) for your convinence. 26 | 27 | We also provide standalone makefiles for Windows, Mac OS X (Darwin), 28 | DOS (DJGPP), OS/2, as well as MorphOS, AmigaOS and AROS. 29 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ACLOCAL_AMFLAGS = -I m4 2 | 3 | SUBDIRS = src tests 4 | 5 | pcdata_DATA= libtimidity.pc 6 | pcdatadir = $(libdir)/pkgconfig 7 | 8 | EXTRA_DIST = CHANGES COPYING.artistic README.timidity TODO 9 | 10 | dist-hook: 11 | cp libtimidity.spec $(distdir) 12 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | libTiMidity -- MIDI to WAVE converter library. 2 | 3 | This library is based on the TiMidity decoder from SDL_sound library. 4 | Purpose to create this library is to avoid unnecessary dependences. 5 | SDL_sound requires SDL and some other libraries, that not needed to 6 | process MIDI files. In addition libTiMidity provides more suitable 7 | API to work with MIDI songs, it enables to specify full path to the 8 | timidity configuration file, and have function to retrieve meta data 9 | from MIDI song. 10 | 11 | If you have propositions regarding development of this library please 12 | contact us through the project page at: https://sf.net/p/libtimidity/ 13 | -------------------------------------------------------------------------------- /README.timidity: -------------------------------------------------------------------------------- 1 | ---------------------------------*-text-*--------------------------------- 2 | 3 | TiMidity -- Experimental MIDI to WAVE converter 4 | Copyright (C) 1995 Tuukka Toivonen 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 | 20 | -------------------------------------------------------------------------- 21 | 22 | This is the README file for TiMidity v0.2i 23 | 24 | TiMidity is a MIDI to WAVE converter that uses Gravis 25 | Ultrasound(*)-compatible patch files to generate digital audio data 26 | from General MIDI files. The audio data can be played through any 27 | sound device or stored on disk. On a fast machine, music can be 28 | played in real time. TiMidity runs under Linux, FreeBSD, HP-UX, SunOS, and 29 | Win32, and porting to other systems with gcc should be easy. 30 | 31 | TiMidity Features: 32 | 33 | * 32 or more dynamically allocated fully independent voices 34 | * Compatibility with GUS patch files 35 | * Output to 16- or 8-bit PCM or uLaw audio device, file, or 36 | stdout at any sampling rate 37 | * Optional interactive mode with real-time status display 38 | under ncurses and SLang terminal control libraries. Also 39 | a user friendly motif interface since version 0.2h 40 | * Support for transparent loading of compressed MIDI files and 41 | patch files 42 | 43 | * Support for the following MIDI events: 44 | - Program change 45 | - Key pressure 46 | - Channel main volume 47 | - Tempo 48 | - Panning 49 | - Damper pedal (Sustain) 50 | - Pitch wheel 51 | - Pitch wheel sensitivity 52 | - Change drum set 53 | 54 | * The file "CHANGES" contains a brief list of what has changed since 55 | the previous version. Please check it if you've been using a TiMidity 56 | version older than 0.2d. You may have to modify your configuration 57 | files slightly -- look at the included "gravis.cfg" for examples. 58 | 59 | * Installation instructions are in the file "INSTALL". 60 | 61 | * Instructions for use can be found in the manual page "timidity.man", 62 | preformatted in "timidity.txt", and in comments in the configuration 63 | files. 64 | 65 | * The GNU General Public License can, as always, be found in the file 66 | "COPYING". 67 | 68 | * TiMidity requires sampled instruments (patches) to play MIDI files. You 69 | should get the file "timidity-lib-0.1.tar.gz" and unpack it in the same 70 | directory where you unpacked the source code archive. You'll want more 71 | patches later -- read the file "FAQ" for pointers. 72 | 73 | * The latest version of TiMidity can be found on the TiMidity Home Page, 74 | URL http://www.clinet.fi/~toivonen/timidity/ 75 | 76 | An alternative URL for Motif version is http://www.loria.fr/~pagel 77 | 78 | * If you have any comments or suggestions, please email me! 79 | 80 | 81 | Tuukka Toivonen 82 | 83 | [(*) Any Registered Trademarks used anywhere in the documentation or 84 | source code for TiMidity are acknowledged as belonging to their 85 | respective owners.] 86 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | * Need documentation 2 | * Error handling API (mid_errno, mid_strerror) 3 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.59]) 5 | AC_INIT([libtimidity],[0.2.7]) 6 | LIBTIMIDITY_MAJOR_VERSION=0 7 | LIBTIMIDITY_MINOR_VERSION=2 8 | LIBTIMIDITY_MICRO_VERSION=7 9 | LIBTIMIDITY_VERSION=$LIBTIMIDITY_MAJOR_VERSION.$LIBTIMIDITY_MINOR_VERSION.$LIBTIMIDITY_MICRO_VERSION 10 | 11 | AC_CONFIG_AUX_DIR([autotools]) 12 | AM_INIT_AUTOMAKE([1.7 foreign]) 13 | AC_CONFIG_MACRO_DIR([m4]) 14 | AC_CONFIG_SRCDIR([src/playmidi.c]) 15 | AM_MAINTAINER_MODE 16 | 17 | # Library versioning for libtool: CURRENT, REVISION, AGE 18 | # - library source changed -> increment REVISION 19 | # - interfaces added/removed/changed -> increment CURRENT, REVISION = 0 20 | # - interfaces added -> increment AGE 21 | # - interfaces removed -> AGE = 0 22 | LIBTIMIDITY_LT_CURRENT=2 23 | LIBTIMIDITY_LT_REVISION=1 24 | LIBTIMIDITY_LT_AGE=0 25 | 26 | AC_CANONICAL_HOST 27 | 28 | AC_ARG_ENABLE([lookup-sine],[AS_HELP_STRING([--enable-lookup-sine],[use sine lookup table [default=no]])],,[enable_lookup_sine=no]) 29 | if test x$enable_lookup_sine = xyes 30 | then 31 | AC_DEFINE([LOOKUP_SINE], 1, [Use a lookup table for sine values]) 32 | fi 33 | 34 | AC_ARG_ENABLE([debug],[AS_HELP_STRING([--enable-debug],[enable debug mode [default=no]])],,[enable_debug=no]) 35 | if test x$enable_debug = xyes 36 | then 37 | AC_DEFINE([TIMIDITY_DEBUG], 1, [Debug mode]) 38 | fi 39 | 40 | AC_ARG_WITH([timidity-cfg],[AS_HELP_STRING([--with-timidity-cfg=FILE],[Specify the full path to timidity.cfg [default="timidity.cfg"]])], 41 | timidity_cfg="$withval", timidity_cfg="timidity.cfg") 42 | if test x$timidity_cfg = xyes || test x$timidity_cfg = xno 43 | then 44 | timidity_cfg="timidity.cfg" 45 | fi 46 | AC_DEFINE_UNQUOTED(TIMIDITY_CFG, "$timidity_cfg", [Define the full path of timidity.cfg]) 47 | 48 | # Checks for programs. 49 | AC_PROG_CC 50 | AC_PROG_CPP 51 | AC_PROG_INSTALL 52 | AC_PROG_LN_S 53 | AC_PROG_EGREP 54 | AC_PROG_MAKE_SET 55 | LT_INIT([win32-dll]) 56 | 57 | if test $ac_cv_c_compiler_gnu = yes 58 | then 59 | CFLAGS="$CFLAGS -Wall" 60 | fi 61 | 62 | # Checks for libraries. 63 | LIBTIMIDITY_LIBS="" 64 | use_libm=no 65 | old_LIBS="${LIBS}" 66 | case "${host_os}" in 67 | dnl These system don't have libm, or don't need it 68 | darwin*|mingw*|cygwin*|cegcc*|pw32*|beos*|haiku*) 69 | ;; 70 | *) AC_CHECK_LIB([m], [sin], [use_libm=yes]) 71 | ;; 72 | esac 73 | if test $use_libm = yes && test x$enable_lookup_sine != xyes 74 | then 75 | LIBTIMIDITY_LIBS="-lm" 76 | fi 77 | 78 | have_ao=no 79 | AC_ARG_ENABLE([ao],[AS_HELP_STRING([--disable-ao],[disable building libao-depending programs])],,[enable_ao=yes]) 80 | if test x$enable_ao = xyes 81 | then 82 | XIPH_PATH_AO([have_ao=yes]) 83 | fi 84 | AM_CONDITIONAL([HAVE_AO], [test $have_ao = yes]) 85 | 86 | # Checks for header files. 87 | dnl AC_CHECK_INCLUDES_DEFAULT is an autoconf-2.7x thing where AC_HEADER_STDC is deprecated. 88 | m4_ifdef([AC_CHECK_INCLUDES_DEFAULT], [AC_CHECK_INCLUDES_DEFAULT], [AC_HEADER_STDC]) 89 | 90 | AC_CHECK_HEADERS([sys/param.h unistd.h math.h]) 91 | 92 | # Checks for typedefs, structures, and compiler characteristics. 93 | AC_C_INLINE 94 | AC_C_CONST 95 | AC_TYPE_SIZE_T 96 | AC_C_BIGENDIAN 97 | 98 | # symbol visibility 99 | ac_save_CFLAGS="$CFLAGS" 100 | CFLAGS="$CFLAGS -fvisibility=hidden -Werror" 101 | AC_CACHE_CHECK([if compiler supports visibility attributes],[libtimidity_cv_gcc_visibility], 102 | AC_LANG_PUSH([C]) 103 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 104 | __attribute__((visibility("default"))) int foo(void); 105 | __attribute__((visibility("hidden"))) int bar(void); 106 | int foo(void) { return 0; } 107 | int bar(void) { return 1; }]], [])], 108 | [libtimidity_cv_gcc_visibility=yes], 109 | [libtimidity_cv_gcc_visibility=no]) 110 | AC_LANG_POP([C])) 111 | # we want symbol -fvisibility for elf targets, however it works 112 | # with darwin/macho too. other than that, windows, dos, os/2, amiga 113 | # do not need it: for any such targets, the -Werror switch is 114 | # supposed to fail the above check. (I'm adding the manual test 115 | # below nonetheless, just in case.) 116 | case $host_os in 117 | mingw*|cygwin*|emx*|*djgpp|amigaos*|aros*|morphos*) 118 | libtimidity_cv_gcc_visibility=no 119 | ;; 120 | esac 121 | CFLAGS="$ac_save_CFLAGS" 122 | if test $libtimidity_cv_gcc_visibility = yes 123 | then 124 | SYM_VISIBILITY="-DSYM_VISIBILITY -fvisibility=hidden" 125 | fi 126 | 127 | AC_SUBST(LIBTIMIDITY_MAJOR_VERSION) 128 | AC_SUBST(LIBTIMIDITY_MINOR_VERSION) 129 | AC_SUBST(LIBTIMIDITY_MICRO_VERSION) 130 | AC_SUBST(LIBTIMIDITY_VERSION) 131 | AC_SUBST(LIBTIMIDITY_LT_CURRENT) 132 | AC_SUBST(LIBTIMIDITY_LT_REVISION) 133 | AC_SUBST(LIBTIMIDITY_LT_AGE) 134 | 135 | AC_SUBST(LIBTIMIDITY_LIBS) 136 | 137 | AC_SUBST(SYM_VISIBILITY) 138 | 139 | AC_CONFIG_FILES([Makefile 140 | libtimidity.pc 141 | libtimidity.spec 142 | src/Makefile 143 | tests/Makefile]) 144 | AC_CONFIG_HEADERS([config.h]) 145 | AC_OUTPUT 146 | -------------------------------------------------------------------------------- /libtimidity.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: libtimidity 7 | Description: MIDI to WAVE converter library 8 | Version: @LIBTIMIDITY_VERSION@ 9 | URL: http://libtimidity.sourceforge.net/ 10 | Libs: -L${libdir} -ltimidity 11 | Libs.private: @LIBTIMIDITY_LIBS@ 12 | Cflags: -I${includedir} 13 | -------------------------------------------------------------------------------- /libtimidity.spec.in: -------------------------------------------------------------------------------- 1 | Summary: MIDI to WAVE converter library 2 | Name: libtimidity 3 | Version: @LIBTIMIDITY_VERSION@ 4 | Release: 1 5 | License: LGPL 6 | Group: System Environment/Libraries 7 | Source: %{name}-%{version}.tar.gz 8 | BuildRoot: %{_tmppath}/%{name}-%{version}-root 9 | 10 | %description 11 | libTiMidity is MIDI to WAVE converter library. It based on the 12 | TiMidity decoder from SDL_sound library. Purpose to create this 13 | library is to avoid unnecessary dependences. SDL_sound requires 14 | SDL and some other libraries, that not needed to process MIDI 15 | files. In addition libTiMidity provides more suitable API to work 16 | with MIDI songs, it enables to specify full path to the timidity 17 | configuration file, and have function to retrieve meta data from 18 | MIDI song. 19 | 20 | %package devel 21 | Summary: The development libraries and header files for %{name} 22 | Group: Development/C 23 | Requires: %{name} = %{version}-%{release} 24 | 25 | %description devel 26 | These are the development libraries and header files for %{name} 27 | 28 | %prep 29 | %setup -q 30 | 31 | %build 32 | %configure 33 | make 34 | 35 | %install 36 | rm -rf "$RPM_BUILD_ROOT" 37 | mkdir -p "$RPM_BUILD_ROOT" 38 | make DESTDIR="$RPM_BUILD_ROOT" install 39 | 40 | %clean 41 | rm -rf "$RPM_BUILD_ROOT" 42 | 43 | %post -p /sbin/ldconfig 44 | 45 | %postun -p /sbin/ldconfig 46 | 47 | %files 48 | %defattr(-, root, root) 49 | %doc AUTHORS CHANGES COPYING README README.timidity TODO 50 | %{_libdir}/libtimidity.so.* 51 | 52 | %files devel 53 | %defattr(-, root, root) 54 | %{_includedir}/timidity.h 55 | %{_libdir}/libtimidity.so 56 | %{_libdir}/libtimidity.*a 57 | %{_libdir}/pkgconfig 58 | -------------------------------------------------------------------------------- /m4/ao.m4: -------------------------------------------------------------------------------- 1 | # ao.m4 2 | # Configure paths for libao 3 | # Jack Moffitt 10-21-2000 4 | # Shamelessly stolen from Owen Taylor and Manish Singh 5 | 6 | dnl XIPH_PATH_AO([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) 7 | dnl Test for libao, and define AO_CFLAGS and AO_LIBS 8 | dnl 9 | AC_DEFUN([XIPH_PATH_AO], 10 | [dnl 11 | dnl Get the cflags and libraries 12 | dnl 13 | AC_ARG_WITH(ao,[ --with-ao=PFX Prefix where libao is installed (optional)], ao_prefix="$withval", ao_prefix="") 14 | AC_ARG_WITH(ao-libraries,[ --with-ao-libraries=DIR Directory where libao library is installed (optional)], ao_libraries="$withval", ao_libraries="") 15 | AC_ARG_WITH(ao-includes,[ --with-ao-includes=DIR Directory where libao header files are installed (optional)], ao_includes="$withval", ao_includes="") 16 | AC_ARG_ENABLE(aotest, [ --disable-aotest Do not try to compile and run a test ao program],, enable_aotest=yes) 17 | 18 | 19 | if test "x$ao_libraries" != "x" ; then 20 | AO_LIBS="-L$ao_libraries" 21 | elif test "x$ao_prefix" != "x"; then 22 | AO_LIBS="-L$ao_prefix/lib" 23 | elif test "x$prefix" != "xNONE"; then 24 | AO_LIBS="-L$prefix/lib" 25 | fi 26 | 27 | if test "x$ao_includes" != "x" ; then 28 | AO_CFLAGS="-I$ao_includes" 29 | elif test "x$ao_prefix" != "x"; then 30 | AO_CFLAGS="-I$ao_prefix/include" 31 | elif test "x$prefix" != "xNONE"; then 32 | AO_CFLAGS="-I$prefix/include" 33 | fi 34 | 35 | # see where dl* and friends live 36 | AC_CHECK_FUNCS(dlopen, [AO_DL_LIBS=""], [ 37 | AC_CHECK_LIB(dl, dlopen, [AO_DL_LIBS="-ldl"], [ 38 | AC_MSG_WARN([could not find dlopen() needed by libao sound drivers 39 | your system may not be supported.]) 40 | ]) 41 | ]) 42 | 43 | AO_LIBS="$AO_LIBS -lao $AO_DL_LIBS" 44 | 45 | AC_MSG_CHECKING(for ao) 46 | no_ao="" 47 | 48 | 49 | if test "x$enable_aotest" = "xyes" ; then 50 | ac_save_CFLAGS="$CFLAGS" 51 | ac_save_LIBS="$LIBS" 52 | CFLAGS="$CFLAGS $AO_CFLAGS" 53 | LIBS="$LIBS $AO_LIBS" 54 | dnl 55 | dnl Now check if the installed ao is sufficiently new. 56 | dnl 57 | rm -f conf.aotest 58 | AC_RUN_IFELSE([AC_LANG_SOURCE([[ 59 | #include 60 | #include 61 | #include 62 | #include 63 | 64 | int main () 65 | { 66 | system("touch conf.aotest"); 67 | return 0; 68 | } 69 | 70 | ]])],[], [no_ao=yes],[echo $ac_n "cross compiling; assumed OK... $ac_c"]) 71 | CFLAGS="$ac_save_CFLAGS" 72 | LIBS="$ac_save_LIBS" 73 | fi 74 | 75 | if test "x$no_ao" = "x" ; then 76 | AC_MSG_RESULT(yes) 77 | ifelse([$1], , :, [$1]) 78 | else 79 | AC_MSG_RESULT(no) 80 | if test -f conf.aotest ; then 81 | : 82 | else 83 | echo "*** Could not run ao test program, checking why..." 84 | CFLAGS="$CFLAGS $AO_CFLAGS" 85 | LIBS="$LIBS $AO_LIBS" 86 | AC_LINK_IFELSE([AC_LANG_PROGRAM([[ 87 | #include 88 | #include 89 | ]], [[ return 0; ]])], 90 | [ echo "*** The test program compiled, but did not run. This usually means" 91 | echo "*** that the run-time linker is not finding ao or finding the wrong" 92 | echo "*** version of ao. If it is not finding ao, you'll need to set your" 93 | echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" 94 | echo "*** to the installed location Also, make sure you have run ldconfig if that" 95 | echo "*** is required on your system" 96 | echo "***" 97 | echo "*** If you have an old version installed, it is best to remove it, although" 98 | echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], 99 | [ echo "*** The test program failed to compile or link. See the file config.log for the" 100 | echo "*** exact error that occured. This usually means ao was incorrectly installed" 101 | echo "*** or that you have moved ao since it was installed." ]) 102 | CFLAGS="$ac_save_CFLAGS" 103 | LIBS="$ac_save_LIBS" 104 | fi 105 | AO_CFLAGS="" 106 | AO_LIBS="" 107 | ifelse([$2], , :, [$2]) 108 | fi 109 | AC_SUBST(AO_CFLAGS) 110 | AC_SUBST(AO_LIBS) 111 | rm -f conf.aotest 112 | ]) 113 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | AM_CPPFLAGS = -I$(top_srcdir) 2 | 3 | SYM_VISIBILITY = @SYM_VISIBILITY@ 4 | 5 | # always define TIMIDITY_BUILD when building libtimidity 6 | # regardless of static build or shared library build 7 | AM_CFLAGS = -DTIMIDITY_BUILD=1 $(SYM_VISIBILITY) 8 | 9 | lib_LTLIBRARIES = libtimidity.la 10 | 11 | include_HEADERS = timidity.h 12 | 13 | EXTRA_DIST = \ 14 | Makefile.darwin \ 15 | Makefile.mingw \ 16 | Makefile.os2 \ 17 | Makefile.emx \ 18 | Makefile.dj \ 19 | Makefile.morphos \ 20 | Makefile.amigaos \ 21 | Makefile.vbcc \ 22 | Makefile.aros \ 23 | Makefile.w32 \ 24 | VisualStudio \ 25 | XCode 26 | 27 | libtimidity_la_SOURCES = \ 28 | common.c \ 29 | common.h \ 30 | instrum.c \ 31 | instrum.h \ 32 | mix.c \ 33 | mix.h \ 34 | options.h \ 35 | ospaths.h \ 36 | output.c \ 37 | output.h \ 38 | playmidi.c \ 39 | playmidi.h \ 40 | readmidi.c \ 41 | readmidi.h \ 42 | resample.c \ 43 | resample.h \ 44 | stream.c \ 45 | tables.c \ 46 | tables.h \ 47 | timi_endian.h \ 48 | timidity.c \ 49 | timidity.h \ 50 | timidity_internal.h 51 | 52 | libtimidity_la_LDFLAGS = -no-undefined -version-info @LIBTIMIDITY_LT_CURRENT@:@LIBTIMIDITY_LT_REVISION@:@LIBTIMIDITY_LT_AGE@ 53 | libtimidity_la_LIBADD = @LIBTIMIDITY_LIBS@ 54 | -------------------------------------------------------------------------------- /src/Makefile.amigaos: -------------------------------------------------------------------------------- 1 | # GNU Makefile for targeting m86k-amigaos and ppc-amigaos using GCC. 2 | 3 | ifeq ($(CROSS),) 4 | CC=gcc 5 | AS=as 6 | AR=ar 7 | RANLIB=ranlib 8 | else 9 | CC=$(CROSS)-gcc 10 | AS=$(CROSS)-as 11 | AR=$(CROSS)-ar 12 | RANLIB=$(CROSS)-ranlib 13 | endif 14 | 15 | # compiler flags 16 | CFLAGS =-O2 -Wall 17 | CFLAGS +=-ffast-math -fno-common 18 | #CFLAGS +=-g 19 | 20 | # flags for C library choice 21 | #CRT_FLAGS=-mcrt=clib2 22 | #CRT_FLAGS=-mcrt=newlib 23 | CRT_FLAGS=-noixemul 24 | CFLAGS +=$(CRT_FLAGS) 25 | 26 | INCLUDE =-I. 27 | ARFLAGS = cr 28 | CPPFLAGS =-DTIMIDITY_BUILD 29 | CPPFLAGS+=-DWORDS_BIGENDIAN=1 30 | #CPPFLAGS+=-DLOOKUP_SINE 31 | 32 | # for amigaos4 (not really needed) 33 | #CPPFLAGS+=-D__USE_INLINE__ 34 | #CPPFLAGS+=-D__USE_OLD_TIMEVAL__ 35 | 36 | # to build a debug version : 37 | #CPPFLAGS+= -DTIMIDITY_DEBUG 38 | 39 | COMPILE=$(CC) $(CFLAGS) $(INCLUDE) $(CPPFLAGS) -c 40 | 41 | .SUFFIXES: 42 | .SUFFIXES: .o .c 43 | 44 | LIB=libtimidity.a 45 | 46 | OBJ=common.o instrum.o mix.o output.o playmidi.o readmidi.o resample.o stream.o tables.o timidity.o 47 | 48 | all: $(LIB) 49 | 50 | clean: 51 | $(RM) $(LIB) *.lib *.o 52 | 53 | $(LIB): $(OBJ) 54 | $(AR) $(ARFLAGS) $@ $(OBJ) 55 | $(RANLIB) $@ 56 | 57 | .c.o: 58 | $(COMPILE) -o $@ $< 59 | -------------------------------------------------------------------------------- /src/Makefile.aros: -------------------------------------------------------------------------------- 1 | # GNU Makefile for targeting i386-aros using GCC. 2 | 3 | ifeq ($(CROSS),) 4 | CC=gcc 5 | AS=as 6 | AR=ar 7 | RANLIB=ranlib 8 | else 9 | CC=$(CROSS)-gcc 10 | AS=$(CROSS)-as 11 | AR=$(CROSS)-ar 12 | RANLIB=$(CROSS)-ranlib 13 | endif 14 | 15 | # compiler flags 16 | CFLAGS =-O2 -Wall 17 | CFLAGS +=-ffast-math -fno-common 18 | #CFLAGS +=-g 19 | INCLUDE =-I. 20 | ARFLAGS = cr 21 | CPPFLAGS =-DTIMIDITY_BUILD 22 | #CPPFLAGS+=-DLOOKUP_SINE 23 | 24 | # to build a debug version : 25 | #CPPFLAGS+= -DTIMIDITY_DEBUG 26 | 27 | COMPILE=$(CC) $(CFLAGS) $(INCLUDE) $(CPPFLAGS) -c 28 | 29 | .SUFFIXES: 30 | .SUFFIXES: .o .c 31 | 32 | LIB=libtimidity.a 33 | 34 | OBJ=common.o instrum.o mix.o output.o playmidi.o readmidi.o resample.o stream.o tables.o timidity.o 35 | 36 | all: $(LIB) 37 | 38 | clean: 39 | $(RM) $(LIB) *.lib *.o 40 | 41 | $(LIB): $(OBJ) 42 | $(AR) $(ARFLAGS) $@ $(OBJ) 43 | $(RANLIB) $@ 44 | 45 | .c.o: 46 | $(COMPILE) -o $@ $< 47 | -------------------------------------------------------------------------------- /src/Makefile.darwin: -------------------------------------------------------------------------------- 1 | # libtimidity Makefile for targetting Darwin (i.e. Mac OS X) 2 | # Edit the compiler/linker flags, etc. to meet your needs 3 | 4 | ifeq ($(CROSS),) 5 | CC=gcc 6 | AS=as 7 | AR=ar 8 | RANLIB=ranlib 9 | LIPO=lipo 10 | else 11 | CC=$(CROSS)-gcc 12 | AS=$(CROSS)-as 13 | AR=$(CROSS)-ar 14 | RANLIB=$(CROSS)-ranlib 15 | LIPO=$(CROSS)-lipo 16 | endif 17 | 18 | ARFLAGS = cr 19 | CPPFLAGS=-DTIMIDITY_BUILD 20 | LDLIBS= 21 | # to build a debug version : 22 | #CPPFLAGS+= -DTIMIDITY_DEBUG 23 | 24 | # compiler flags 25 | CFLAGS=-O2 -Wall 26 | CFLAGS+=-fno-common -ffast-math 27 | CFLAGS+=-fvisibility=hidden -DSYM_VISIBILITY 28 | #CFLAGS+=-g 29 | LDFLAGS =-dynamiclib -Wl,-single_module 30 | LDFLAGS+=-Wl,-undefined,error 31 | LDFLAGS+=-Wl,-install_name,"@executable_path/$(LIBSHARED)" 32 | LDFLAGS+=-Wl,-compatibility_version,3.0 -Wl,-current_version,3.1 33 | 34 | # specifically for 10.5 and newer: 35 | #CFLAGS+=-mmacosx-version-min=10.5 36 | #LDFLAGS+=-mmacosx-version-min=10.5 37 | # specifically for 10.6 and newer: 38 | #CFLAGS+=-mmacosx-version-min=10.6 39 | #LDFLAGS+=-mmacosx-version-min=10.6 -Wl,-lbundle1.o 40 | 41 | COMPILE=$(CC) $(CFLAGS) $(CPPFLAGS) -I. -c 42 | 43 | .SUFFIXES: 44 | .SUFFIXES: .o .c 45 | 46 | DYLIB_VER=2 47 | #LIBSHARED=libtimidity.$(DYLIB_VER).dylib 48 | LIBSHARED=libtimidity.dylib 49 | LIBSTATIC=libtimidity.a 50 | 51 | LIBS=$(LIBSHARED) 52 | 53 | OBJ=common.o instrum.o mix.o output.o playmidi.o readmidi.o resample.o stream.o tables.o timidity.o 54 | 55 | help: 56 | @echo "Valid targets:" 57 | @echo "" 58 | @echo " $(MAKE) dylib : build libtimidity.dylib shared lib" 59 | @echo " $(MAKE) static : build libtimidity.a static library" 60 | @echo "" 61 | 62 | clean: 63 | rm -f $(LIBSHARED) $(LIBSTATIC) *.o 64 | 65 | dylib: $(LIBSHARED) 66 | static: $(LIBSTATIC) 67 | 68 | $(LIBSHARED): $(OBJ) 69 | $(CC) -o $(LIBSHARED) $(OBJ) $(LDFLAGS) $(LDLIBS) 70 | 71 | $(LIBSTATIC): $(OBJ) 72 | $(AR) $(ARFLAGS) $@ $(OBJ) 73 | $(RANLIB) $@ 74 | 75 | .c.o: 76 | $(COMPILE) -o $@ $< 77 | -------------------------------------------------------------------------------- /src/Makefile.dj: -------------------------------------------------------------------------------- 1 | # GNU Makefile for targeting DOS using DJGPP (GCC) 2 | # (DJGPP-2.05 or newer is required for DXE3 build.) 3 | 4 | ifeq ($(CROSS),) 5 | CC=gcc 6 | AS=as 7 | AR=ar 8 | RANLIB=ranlib 9 | else 10 | CC=$(CROSS)-gcc 11 | AS=$(CROSS)-as 12 | AR=$(CROSS)-ar 13 | RANLIB=$(CROSS)-ranlib 14 | endif 15 | DXE3GEN=dxe3gen 16 | 17 | CPPFLAGS = -DTIMIDITY_BUILD 18 | #CPPFLAGS+=-DLOOKUP_SINE 19 | ARFLAGS = cr 20 | # to build a debug version : 21 | #CPPFLAGS+= -DTIMIDITY_DEBUG 22 | 23 | CFLAGS = -O2 -Wall -ffast-math 24 | 25 | .SUFFIXES: 26 | .SUFFIXES: .o .c 27 | 28 | COMPILE=$(CC) $(CFLAGS) $(CPPFLAGS) -I. -c 29 | 30 | OBJ=common.o instrum.o mix.o output.o playmidi.o readmidi.o resample.o stream.o tables.o timidity.o 31 | 32 | .PHONY: clean 33 | 34 | # The build targets 35 | TARGETS = libtimidity.a libtimidity_dxe.a timidity.dxe 36 | 37 | all: $(TARGETS) 38 | 39 | clean: 40 | $(RM) *.o *.a *.dxe 41 | 42 | libtimidity.a: $(OBJ) 43 | $(AR) $(ARFLAGS) $@ $^ 44 | $(RANLIB) $@ 45 | 46 | libtimidity_dxe.a: timidity.dxe 47 | timidity.dxe: $(OBJ) 48 | -$(DXE3GEN) -Y libtimidity_dxe.a -o $@ -E _mid_ -U $^ 49 | 50 | .c.o: 51 | $(COMPILE) -o $@ $< 52 | 53 | -------------------------------------------------------------------------------- /src/Makefile.emx: -------------------------------------------------------------------------------- 1 | # Makefile for OS/2 using EMX environment. 2 | # builds timidity.a static library 3 | 4 | CC=gcc 5 | AS=as 6 | AR=ar 7 | RANLIB=ranlib 8 | LD=$(CC) 9 | 10 | CFLAGS = -I. -Wall -Zmt 11 | CPPFLAGS = -DTIMIDITY_BUILD 12 | #CPPFLAGS+=-DLOOKUP_SINE 13 | # to build a debug version: 14 | #CPPFLAGS+= -DTIMIDITY_DEBUG 15 | LDFLAGS = -Zmt 16 | ARFLAGS = cr 17 | 18 | ifeq ($(DEBUG),1) 19 | CFLAGS += -g 20 | else 21 | CFLAGS += -O2 -ffast-math 22 | LDFLAGS+= -s 23 | endif 24 | 25 | LIBSTATIC=timidity.a 26 | 27 | OBJ=common.o instrum.o mix.o output.o playmidi.o readmidi.o resample.o stream.o tables.o timidity.o 28 | 29 | all: $(LIBSTATIC) 30 | 31 | $(LIBSTATIC): $(OBJ) 32 | $(AR) $(ARFLAGS) $@ $^ 33 | -$(RANLIB) $@ 34 | 35 | %.o: %.c 36 | $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $< 37 | 38 | clean: 39 | $(RM) *.o 40 | distclean: clean 41 | $(RM) $(LIBSTATIC) 42 | -------------------------------------------------------------------------------- /src/Makefile.mingw: -------------------------------------------------------------------------------- 1 | # Makefile for targetting win32/win64 2 | # Requires a native or cross MinGW or MinGW-w64 compiler-set 3 | # and GNU make (gmake or mingw32-make or whatever) 4 | 5 | ifeq ($(CROSS),) 6 | CC=gcc 7 | AS=as 8 | AR=ar 9 | RANLIB=ranlib 10 | else 11 | CC=$(CROSS)-gcc 12 | AS=$(CROSS)-as 13 | AR=$(CROSS)-ar 14 | RANLIB=$(CROSS)-ranlib 15 | endif 16 | #RM=del 17 | RM=rm -f 18 | 19 | ARFLAGS = cr 20 | CPPFLAGS=-DTIMIDITY_BUILD 21 | #CPPFLAGS+=-DLOOKUP_SINE 22 | LDLIBS= 23 | # to build a debug version : 24 | #CPPFLAGS+= -DTIMIDITY_DEBUG 25 | 26 | # Compiler flags 27 | CFLAGS=-O2 -Wall 28 | CFLAGS+=-ffast-math 29 | #CFLAGS+=-g 30 | LDFLAGS= 31 | #LDLIBS+=-lm 32 | 33 | COMPILE=$(CC) $(CFLAGS) $(CPPFLAGS) -I. -c 34 | 35 | .SUFFIXES: 36 | .SUFFIXES: .o .c 37 | 38 | DLL_VER=2 39 | 40 | CPPFLAGS_DLL=-DDLL_EXPORT=1 41 | CPPFLAGS_STATIC=-DTIMIDITY_STATIC=1 42 | 43 | LIBNAME=libtimidity.dll.a 44 | LIBSTATIC=libtimidity.a 45 | DLLNAME=libtimidity-$(DLL_VER).dll 46 | DEFNAME=libtimidity-$(DLL_VER).def 47 | 48 | LIBS=$(LIBNAME) $(DLLNAME) 49 | 50 | OBJ=common.o instrum.o mix.o output.o playmidi.o readmidi.o resample.o stream.o tables.o timidity.o 51 | 52 | help: 53 | @echo "Valid targets:" 54 | @echo "" 55 | @echo " $(MAKE) dll : build dll and import library" 56 | @echo " $(MAKE) static : build static library" 57 | @echo "" 58 | 59 | clean: 60 | $(RM) $(DLLNAME) $(LIBNAME) $(LIBSTATIC) $(DEFNAME) *.o 61 | 62 | dll: $(DLLNAME) $(LIBNAME) 63 | static: $(LIBSTATIC) 64 | 65 | $(DLLNAME): CPPFLAGS+=$(CPPFLAGS_DLL) 66 | $(LIBNAME): $(DLLNAME) 67 | $(DLLNAME): $(OBJ) 68 | $(CC) -shared -o $(DLLNAME) $(OBJ) $(LDFLAGS) $(LDLIBS) \ 69 | -Wl,--enable-auto-image-base -Wl,--no-undefined \ 70 | -Xlinker --output-def -Xlinker $(DEFNAME) \ 71 | -Xlinker --out-implib -Xlinker $(LIBNAME) 72 | 73 | $(LIBSTATIC): CPPFLAGS+=$(CPPFLAGS_STATIC) 74 | $(LIBSTATIC): $(OBJ) 75 | $(AR) $(ARFLAGS) $@ $(OBJ) 76 | $(RANLIB) $@ 77 | 78 | .c.o: 79 | $(COMPILE) -o $@ $< 80 | -------------------------------------------------------------------------------- /src/Makefile.morphos: -------------------------------------------------------------------------------- 1 | # GNU Makefile for targeting ppc-morphos using GCC. 2 | 3 | ifeq ($(CROSS),) 4 | CC=gcc 5 | AS=as 6 | AR=ar 7 | RANLIB=ranlib 8 | else 9 | CC=$(CROSS)-gcc 10 | AS=$(CROSS)-as 11 | AR=$(CROSS)-ar 12 | RANLIB=$(CROSS)-ranlib 13 | endif 14 | 15 | # compiler flags 16 | CFLAGS =-O2 -Wall 17 | CFLAGS +=-noixemul 18 | CFLAGS +=-ffast-math -fno-common 19 | #CFLAGS +=-g 20 | INCLUDE =-I. 21 | ARFLAGS = cr 22 | CPPFLAGS =-DTIMIDITY_BUILD 23 | CPPFLAGS+=-DWORDS_BIGENDIAN=1 24 | #CPPFLAGS+=-DLOOKUP_SINE 25 | 26 | # to build a debug version : 27 | #CPPFLAGS+= -DTIMIDITY_DEBUG 28 | 29 | COMPILE=$(CC) $(CFLAGS) $(INCLUDE) $(CPPFLAGS) -c 30 | 31 | .SUFFIXES: 32 | .SUFFIXES: .o .c 33 | 34 | LIB=libtimidity.a 35 | 36 | OBJ=common.o instrum.o mix.o output.o playmidi.o readmidi.o resample.o stream.o tables.o timidity.o 37 | 38 | all: $(LIB) 39 | 40 | clean: 41 | $(RM) $(LIB) *.lib *.o 42 | 43 | $(LIB): $(OBJ) 44 | $(AR) $(ARFLAGS) $@ $(OBJ) 45 | $(RANLIB) $@ 46 | 47 | .c.o: 48 | $(COMPILE) -o $@ $< 49 | -------------------------------------------------------------------------------- /src/Makefile.os2: -------------------------------------------------------------------------------- 1 | # Makefile for OS/2 using Watcom compiler. 2 | # 3 | # wmake -f Makefile.os2 4 | # - builds timidity.dll and its import lib (timidity.lib) 5 | # 6 | # wmake -f Makefile.os2 target=static 7 | # - builds the static library timidity_static.lib 8 | 9 | !ifndef target 10 | target = dll 11 | !endif 12 | 13 | INCLUDES=-I. 14 | CPPFLAGS=-DTIMIDITY_BUILD 15 | #CPPFLAGS+=-DLOOKUP_SINE 16 | # to enable loud debug messages: 17 | #CPPFLAGS+= -DTIMIDITY_DEBUG 18 | 19 | CFLAGS = -zq -bt=os2 -bm -fp5 -fpi87 -mf -oeatxh -w4 -ei -j -zp8 20 | # -5s : Pentium stack calling conventions. 21 | # -5r : Pentium register calling conventions. 22 | CFLAGS+= -5s 23 | DLLFLAGS=-bd 24 | 25 | .SUFFIXES: 26 | .SUFFIXES: .obj .c 27 | 28 | DLLNAME=timidity.dll 29 | EXPNAME=timidity.exp 30 | LIBNAME=timidity.lib 31 | LIBSTATIC=timidity_static.lib 32 | 33 | !ifeq target static 34 | BLD_TARGET=$(LIBSTATIC) 35 | !else 36 | CFLAGS+= $(DLLFLAGS) 37 | BLD_TARGET=$(DLLNAME) 38 | !endif 39 | 40 | COMPILE=wcc386 $(CFLAGS) $(CPPFLAGS) $(INCLUDES) 41 | 42 | OBJ=common.obj instrum.obj mix.obj output.obj playmidi.obj readmidi.obj resample.obj stream.obj tables.obj timidity.obj 43 | 44 | all: $(BLD_TARGET) 45 | 46 | # rely on symbol name, not ordinal: -irn switch of wlib is default, but -inn is not. 47 | $(DLLNAME): $(OBJ) 48 | wlink NAM $@ OP q SYSTEM os2v2_dll INITINSTANCE TERMINSTANCE OPTION MANYAUTODATA FIL {$(OBJ)} OPTION IMPF=$(EXPNAME) 49 | wlib -q -b -n -c -pa -s -t -zld -ii -io -inn $(LIBNAME) +$(DLLNAME) 50 | 51 | $(LIBSTATIC): $(OBJ) 52 | wlib -q -b -n -c -pa -s -t -zld -ii -io $@ $(OBJ) 53 | 54 | .c.obj: 55 | $(COMPILE) -fo=$^@ $< 56 | 57 | distclean: clean .symbolic 58 | rm -f $(DLLNAME) $(EXPNAME) $(LIBNAME) $(LIBSTATIC) 59 | clean: .symbolic 60 | rm -f *.obj 61 | -------------------------------------------------------------------------------- /src/Makefile.vbcc: -------------------------------------------------------------------------------- 1 | # GNU Makefile for targeting m68k-amigaos using VBCC. 2 | 3 | CC=vc 4 | #MKLIB=join $(OBJ) as $(LIB) 5 | MKLIB=cat $(OBJ) > $(LIB) 6 | 7 | # compiler flags 8 | CFLAGS =-O1 -speed -c99 9 | CFLAGS +=-cpu=68020 -fpu=68881 10 | INCLUDE =-I. 11 | CPPFLAGS =-DTIMIDITY_BUILD 12 | CPPFLAGS+=-D__AMIGA__ 13 | CPPFLAGS+=-DWORDS_BIGENDIAN=1 14 | CPPFLAGS+=-DLOOKUP_SINE 15 | 16 | # to build a debug version : 17 | #CPPFLAGS+= -DTIMIDITY_DEBUG 18 | 19 | COMPILE=$(CC) $(CFLAGS) $(INCLUDE) $(CPPFLAGS) -c 20 | 21 | .SUFFIXES: 22 | .SUFFIXES: .o .c 23 | 24 | LIB=timidity.lib 25 | 26 | OBJ=common.o instrum.o mix.o output.o playmidi.o readmidi.o resample.o stream.o tables.o timidity.o 27 | 28 | all: $(LIB) 29 | 30 | clean: 31 | $(RM) $(LIB) *.a *.o 32 | 33 | $(LIB): $(OBJ) 34 | $(MKLIB) 35 | 36 | .c.o: 37 | $(COMPILE) -o $@ $< 38 | -------------------------------------------------------------------------------- /src/Makefile.w32: -------------------------------------------------------------------------------- 1 | # Makefile for Windows using Open Watcom compiler. 2 | # 3 | # wmake -f Makefile.w32 4 | # - builds timidity.dll and its import library timidity.lib 5 | # 6 | # wmake -f Makefile.w32 target=static 7 | # - builds the static library timidity_static.lib 8 | 9 | !ifndef target 10 | target = dll 11 | !endif 12 | 13 | INCLUDES=-I. 14 | CPPFLAGS=-DTIMIDITY_BUILD 15 | #CPPFLAGS+=-DLOOKUP_SINE 16 | # to enable loud debug messages: 17 | #CPPFLAGS+= -DTIMIDITY_DEBUG 18 | 19 | CFLAGS = -zq -bt=nt -bm -fp5 -fpi87 -mf -oeatxh -w4 -ei -j -zp8 20 | # -5s : Pentium stack calling conventions. 21 | # -5r : Pentium register calling conventions. 22 | CFLAGS+= -5s 23 | DLLFLAGS=-bd 24 | 25 | .SUFFIXES: 26 | .SUFFIXES: .obj .c 27 | 28 | DLLNAME=libtimidity.dll 29 | EXPNAME=libtimidity.exp 30 | LIBNAME=libtimidity.lib 31 | LIBSTATIC=timidity-static.lib 32 | 33 | !ifeq target static 34 | CPPFLAGS+= -DTIMIDITY_STATIC 35 | BLD_TARGET=$(LIBSTATIC) 36 | !else 37 | CPPFLAGS+= -DDLL_EXPORT 38 | CFLAGS+= $(DLLFLAGS) 39 | BLD_TARGET=$(DLLNAME) 40 | !endif 41 | 42 | COMPILE=wcc386 $(CFLAGS) $(CPPFLAGS) $(INCLUDES) 43 | 44 | OBJ=common.obj instrum.obj mix.obj output.obj playmidi.obj readmidi.obj resample.obj stream.obj tables.obj timidity.obj 45 | 46 | all: $(BLD_TARGET) 47 | 48 | # rely on symbol name, not ordinal: -irn switch of wlib is default, but -inn is not. 49 | $(DLLNAME): $(OBJ) 50 | wlink NAM $@ OP q SYSTEM nt_dll INITINSTANCE TERMINSTANCE FIL {$(OBJ)} OPTION IMPF=$(EXPNAME) 51 | wlib -q -b -n -c -pa -s -t -zld -ii -io -inn $(LIBNAME) +$(DLLNAME) 52 | 53 | $(LIBSTATIC): $(OBJ) 54 | wlib -q -b -n -c -pa -s -t -zld -ii -io $@ $(OBJ) 55 | 56 | .c.obj: 57 | $(COMPILE) -fo=$^@ $< 58 | 59 | distclean: clean .symbolic 60 | rm -f $(DLLNAME) $(EXPNAME) $(LIBNAME) $(LIBSTATIC) 61 | clean: .symbolic 62 | rm -f *.obj 63 | -------------------------------------------------------------------------------- /src/VS2005/libtimidity.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 9.00 3 | # Visual Studio 2005 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtimidity", "libtimidity.vcproj", "{75E6C1F0-C323-43E9-AA2E-0C7FC635E36F}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "timidity_static", "timidity_static.vcproj", "{0E8C9A30-E123-426F-9B15-611C21866C64}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Debug|x64 = Debug|x64 12 | Release|Win32 = Release|Win32 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {75E6C1F0-C323-43E9-AA2E-0C7FC635E36F}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {75E6C1F0-C323-43E9-AA2E-0C7FC635E36F}.Debug|Win32.Build.0 = Debug|Win32 18 | {75E6C1F0-C323-43E9-AA2E-0C7FC635E36F}.Debug|x64.ActiveCfg = Debug|x64 19 | {75E6C1F0-C323-43E9-AA2E-0C7FC635E36F}.Debug|x64.Build.0 = Debug|x64 20 | {75E6C1F0-C323-43E9-AA2E-0C7FC635E36F}.Release|Win32.ActiveCfg = Release|Win32 21 | {75E6C1F0-C323-43E9-AA2E-0C7FC635E36F}.Release|Win32.Build.0 = Release|Win32 22 | {75E6C1F0-C323-43E9-AA2E-0C7FC635E36F}.Release|x64.ActiveCfg = Release|x64 23 | {75E6C1F0-C323-43E9-AA2E-0C7FC635E36F}.Release|x64.Build.0 = Release|x64 24 | {0E8C9A30-E123-426F-9B15-611C21866C64}.Debug|Win32.ActiveCfg = Debug|Win32 25 | {0E8C9A30-E123-426F-9B15-611C21866C64}.Debug|Win32.Build.0 = Debug|Win32 26 | {0E8C9A30-E123-426F-9B15-611C21866C64}.Debug|x64.ActiveCfg = Debug|x64 27 | {0E8C9A30-E123-426F-9B15-611C21866C64}.Debug|x64.Build.0 = Debug|x64 28 | {0E8C9A30-E123-426F-9B15-611C21866C64}.Release|Win32.ActiveCfg = Release|Win32 29 | {0E8C9A30-E123-426F-9B15-611C21866C64}.Release|Win32.Build.0 = Release|Win32 30 | {0E8C9A30-E123-426F-9B15-611C21866C64}.Release|x64.ActiveCfg = Release|x64 31 | {0E8C9A30-E123-426F-9B15-611C21866C64}.Release|x64.Build.0 = Release|x64 32 | EndGlobalSection 33 | GlobalSection(SolutionProperties) = preSolution 34 | HideSolutionNode = FALSE 35 | EndGlobalSection 36 | EndGlobal 37 | -------------------------------------------------------------------------------- /src/VS2005/libtimidity.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 17 | 18 | 19 | 20 | 21 | 28 | 31 | 34 | 37 | 40 | 53 | 56 | 59 | 62 | 69 | 72 | 75 | 78 | 81 | 84 | 87 | 90 | 91 | 99 | 102 | 105 | 108 | 111 | 121 | 124 | 127 | 130 | 139 | 142 | 145 | 148 | 151 | 154 | 157 | 160 | 161 | 168 | 171 | 174 | 177 | 181 | 194 | 197 | 200 | 203 | 210 | 213 | 216 | 219 | 222 | 225 | 228 | 231 | 232 | 240 | 243 | 246 | 249 | 253 | 263 | 266 | 269 | 272 | 281 | 284 | 287 | 290 | 293 | 296 | 299 | 302 | 303 | 304 | 305 | 306 | 307 | 312 | 315 | 316 | 319 | 320 | 323 | 324 | 327 | 328 | 331 | 332 | 335 | 336 | 339 | 340 | 343 | 344 | 347 | 348 | 351 | 352 | 353 | 358 | 361 | 362 | 365 | 366 | 369 | 370 | 373 | 374 | 377 | 378 | 381 | 382 | 385 | 386 | 389 | 390 | 393 | 394 | 397 | 398 | 401 | 402 | 405 | 406 | 409 | 410 | 411 | 416 | 417 | 418 | 419 | 420 | 421 | -------------------------------------------------------------------------------- /src/VS2005/timidity_static.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 17 | 18 | 19 | 20 | 21 | 28 | 31 | 34 | 37 | 40 | 53 | 56 | 59 | 62 | 65 | 68 | 71 | 74 | 77 | 80 | 81 | 89 | 92 | 95 | 98 | 101 | 111 | 114 | 117 | 120 | 123 | 126 | 129 | 132 | 135 | 138 | 139 | 146 | 149 | 152 | 155 | 159 | 172 | 175 | 178 | 181 | 184 | 187 | 190 | 193 | 196 | 199 | 200 | 208 | 211 | 214 | 217 | 221 | 231 | 234 | 237 | 240 | 243 | 246 | 249 | 252 | 255 | 258 | 259 | 260 | 261 | 262 | 263 | 268 | 271 | 272 | 275 | 276 | 279 | 280 | 283 | 284 | 287 | 288 | 291 | 292 | 295 | 296 | 299 | 300 | 303 | 304 | 307 | 308 | 309 | 314 | 317 | 318 | 321 | 322 | 325 | 326 | 329 | 330 | 333 | 334 | 337 | 338 | 341 | 342 | 345 | 346 | 349 | 350 | 353 | 354 | 357 | 358 | 361 | 362 | 365 | 366 | 367 | 372 | 373 | 374 | 375 | 376 | 377 | -------------------------------------------------------------------------------- /src/VisualStudio/libtimidity.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtimidity", "libtimidity.vcxproj", "{75E6C1F0-C323-43E9-AA2E-0C7FC635E36F}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "timidity_static", "timidity_static.vcxproj", "{0E8C9A30-E123-426F-9B15-611C21866C64}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Debug|x64 = Debug|x64 12 | Release|Win32 = Release|Win32 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {75E6C1F0-C323-43E9-AA2E-0C7FC635E36F}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {75E6C1F0-C323-43E9-AA2E-0C7FC635E36F}.Debug|Win32.Build.0 = Debug|Win32 18 | {75E6C1F0-C323-43E9-AA2E-0C7FC635E36F}.Debug|x64.ActiveCfg = Debug|x64 19 | {75E6C1F0-C323-43E9-AA2E-0C7FC635E36F}.Debug|x64.Build.0 = Debug|x64 20 | {75E6C1F0-C323-43E9-AA2E-0C7FC635E36F}.Release|Win32.ActiveCfg = Release|Win32 21 | {75E6C1F0-C323-43E9-AA2E-0C7FC635E36F}.Release|Win32.Build.0 = Release|Win32 22 | {75E6C1F0-C323-43E9-AA2E-0C7FC635E36F}.Release|x64.ActiveCfg = Release|x64 23 | {75E6C1F0-C323-43E9-AA2E-0C7FC635E36F}.Release|x64.Build.0 = Release|x64 24 | {0E8C9A30-E123-426F-9B15-611C21866C64}.Debug|Win32.ActiveCfg = Debug|Win32 25 | {0E8C9A30-E123-426F-9B15-611C21866C64}.Debug|Win32.Build.0 = Debug|Win32 26 | {0E8C9A30-E123-426F-9B15-611C21866C64}.Debug|x64.ActiveCfg = Debug|x64 27 | {0E8C9A30-E123-426F-9B15-611C21866C64}.Debug|x64.Build.0 = Debug|x64 28 | {0E8C9A30-E123-426F-9B15-611C21866C64}.Release|Win32.ActiveCfg = Release|Win32 29 | {0E8C9A30-E123-426F-9B15-611C21866C64}.Release|Win32.Build.0 = Release|Win32 30 | {0E8C9A30-E123-426F-9B15-611C21866C64}.Release|x64.ActiveCfg = Release|x64 31 | {0E8C9A30-E123-426F-9B15-611C21866C64}.Release|x64.Build.0 = Release|x64 32 | EndGlobalSection 33 | GlobalSection(SolutionProperties) = preSolution 34 | HideSolutionNode = FALSE 35 | EndGlobalSection 36 | EndGlobal 37 | -------------------------------------------------------------------------------- /src/VisualStudio/libtimidity.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {75E6C1F0-C323-43E9-AA2E-0C7FC635E36F} 23 | libtimidity 24 | 10.0 25 | 26 | 27 | 28 | DynamicLibrary 29 | Unicode 30 | $(DefaultPlatformToolset) 31 | true 32 | 33 | 34 | DynamicLibrary 35 | Unicode 36 | $(DefaultPlatformToolset) 37 | 38 | 39 | DynamicLibrary 40 | Unicode 41 | $(DefaultPlatformToolset) 42 | true 43 | 44 | 45 | DynamicLibrary 46 | Unicode 47 | $(DefaultPlatformToolset) 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | <_ProjectFileVersion>10.0.30319.1 67 | $(SolutionDir)$(Configuration)\ 68 | $(Configuration)\ 69 | true 70 | $(SolutionDir)$(Configuration)\ 71 | $(Configuration)\ 72 | false 73 | $(SolutionDir)$(Platform)\$(Configuration)\ 74 | $(Platform)\$(Configuration)\ 75 | true 76 | $(SolutionDir)$(Platform)\$(Configuration)\ 77 | $(Platform)\$(Configuration)\ 78 | false 79 | AllRules.ruleset 80 | 81 | 82 | AllRules.ruleset 83 | 84 | 85 | AllRules.ruleset 86 | 87 | 88 | AllRules.ruleset 89 | 90 | 91 | 92 | 93 | 94 | Disabled 95 | ..;%(AdditionalIncludeDirectories) 96 | WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;TIMIDITY_BUILD;DLL_EXPORT;%(PreprocessorDefinitions) 97 | true 98 | EnableFastChecks 99 | MultiThreadedDebug 100 | 101 | 102 | Level3 103 | EditAndContinue 104 | CompileAsC 105 | 106 | 107 | true 108 | Console 109 | MachineX86 110 | 111 | 112 | 113 | 114 | ..;%(AdditionalIncludeDirectories) 115 | WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;TIMIDITY_BUILD;DLL_EXPORT;%(PreprocessorDefinitions) 116 | MultiThreaded 117 | 118 | 119 | Level3 120 | CompileAsC 121 | 122 | 123 | false 124 | Console 125 | true 126 | true 127 | MachineX86 128 | 129 | 130 | 131 | 132 | X64 133 | 134 | 135 | Disabled 136 | ..;%(AdditionalIncludeDirectories) 137 | WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;TIMIDITY_BUILD;DLL_EXPORT;%(PreprocessorDefinitions) 138 | true 139 | EnableFastChecks 140 | MultiThreadedDebug 141 | 142 | 143 | Level3 144 | ProgramDatabase 145 | CompileAsC 146 | 147 | 148 | true 149 | Console 150 | MachineX64 151 | 152 | 153 | 154 | 155 | X64 156 | 157 | 158 | ..;%(AdditionalIncludeDirectories) 159 | WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;TIMIDITY_BUILD;DLL_EXPORT;%(PreprocessorDefinitions) 160 | MultiThreaded 161 | 162 | 163 | Level3 164 | CompileAsC 165 | 166 | 167 | false 168 | Console 169 | true 170 | true 171 | MachineX64 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | -------------------------------------------------------------------------------- /src/VisualStudio/libtimidity.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | Source Files 47 | 48 | 49 | 50 | 51 | Header Files 52 | 53 | 54 | Header Files 55 | 56 | 57 | Header Files 58 | 59 | 60 | Header Files 61 | 62 | 63 | Header Files 64 | 65 | 66 | Header Files 67 | 68 | 69 | Header Files 70 | 71 | 72 | Header Files 73 | 74 | 75 | Header Files 76 | 77 | 78 | Header Files 79 | 80 | 81 | Header Files 82 | 83 | 84 | Header Files 85 | 86 | 87 | Header Files 88 | 89 | 90 | -------------------------------------------------------------------------------- /src/VisualStudio/timidity_static.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {0E8C9A30-E123-426F-9B15-611C21866C64} 23 | timidity_static 24 | 10.0 25 | 26 | 27 | 28 | StaticLibrary 29 | Unicode 30 | $(DefaultPlatformToolset) 31 | true 32 | 33 | 34 | StaticLibrary 35 | Unicode 36 | $(DefaultPlatformToolset) 37 | 38 | 39 | StaticLibrary 40 | Unicode 41 | $(DefaultPlatformToolset) 42 | true 43 | 44 | 45 | StaticLibrary 46 | Unicode 47 | $(DefaultPlatformToolset) 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | <_ProjectFileVersion>10.0.30319.1 67 | $(SolutionDir)$(Configuration)-static\ 68 | $(Configuration)-static\ 69 | $(SolutionDir)$(Configuration)-static\ 70 | $(Configuration)-static\ 71 | $(SolutionDir)$(Platform)\$(Configuration)-static\ 72 | $(Platform)\$(Configuration)-static\ 73 | $(SolutionDir)$(Platform)\$(Configuration)-static\ 74 | $(Platform)\$(Configuration)-static\ 75 | AllRules.ruleset 76 | 77 | 78 | AllRules.ruleset 79 | 80 | 81 | AllRules.ruleset 82 | 83 | 84 | AllRules.ruleset 85 | 86 | 87 | 88 | 89 | 90 | Disabled 91 | ..;%(AdditionalIncludeDirectories) 92 | WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;TIMIDITY_BUILD;TIMIDITY_STATIC;%(PreprocessorDefinitions) 93 | true 94 | EnableFastChecks 95 | MultiThreadedDebug 96 | 97 | 98 | Level3 99 | EditAndContinue 100 | CompileAsC 101 | 102 | 103 | 104 | 105 | ..;%(AdditionalIncludeDirectories) 106 | WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;TIMIDITY_BUILD;TIMIDITY_STATIC;%(PreprocessorDefinitions) 107 | MultiThreaded 108 | 109 | 110 | Level3 111 | CompileAsC 112 | 113 | 114 | 115 | 116 | X64 117 | 118 | 119 | Disabled 120 | ..;%(AdditionalIncludeDirectories) 121 | WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;TIMIDITY_BUILD;TIMIDITY_STATIC;%(PreprocessorDefinitions) 122 | true 123 | EnableFastChecks 124 | MultiThreadedDebug 125 | 126 | 127 | Level3 128 | ProgramDatabase 129 | CompileAsC 130 | 131 | 132 | 133 | 134 | X64 135 | 136 | 137 | ..;%(AdditionalIncludeDirectories) 138 | WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;TIMIDITY_BUILD;TIMIDITY_STATIC;%(PreprocessorDefinitions) 139 | MultiThreaded 140 | 141 | 142 | Level3 143 | CompileAsC 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /src/VisualStudio/timidity_static.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | Source Files 47 | 48 | 49 | 50 | 51 | Header Files 52 | 53 | 54 | Header Files 55 | 56 | 57 | Header Files 58 | 59 | 60 | Header Files 61 | 62 | 63 | Header Files 64 | 65 | 66 | Header Files 67 | 68 | 69 | Header Files 70 | 71 | 72 | Header Files 73 | 74 | 75 | Header Files 76 | 77 | 78 | Header Files 79 | 80 | 81 | Header Files 82 | 83 | 84 | Header Files 85 | 86 | 87 | Header Files 88 | 89 | 90 | -------------------------------------------------------------------------------- /src/XCode/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | libtimidity 9 | CFBundleName 10 | libtimidity 11 | CFBundleIconFile 12 | 13 | CFBundleIdentifier 14 | 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundlePackageType 18 | FMWK 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 0.2.7 23 | CFBundleShortVersionString 24 | 0.2.7 25 | NSPrincipalClass 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/XCode/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | CFBundleName = "libtimidity"; 4 | CFBundleShortVersionString = "libtimidity version 0.2.7"; 5 | CFBundleGetInfoString = "libtimidity version 0.2.7"; 6 | -------------------------------------------------------------------------------- /src/XCode/libtimidity.exports: -------------------------------------------------------------------------------- 1 | _mid_init 2 | _mid_init_no_config 3 | _mid_exit 4 | _mid_get_version 5 | _mid_istream_open_callbacks 6 | _mid_istream_open_file 7 | _mid_istream_open_fp 8 | _mid_istream_open_mem 9 | _mid_istream_close 10 | _mid_istream_read 11 | _mid_istream_seek 12 | _mid_istream_skip 13 | _mid_istream_tell 14 | _mid_song_load 15 | _mid_song_load_dls 16 | _mid_song_seek 17 | _mid_song_set_volume 18 | _mid_song_start 19 | _mid_song_read_wave 20 | _mid_song_get_meta 21 | _mid_song_get_time 22 | _mid_song_get_total_time 23 | _mid_song_free 24 | _mid_dlspatches_free 25 | _mid_dlspatches_load 26 | -------------------------------------------------------------------------------- /src/common.c: -------------------------------------------------------------------------------- 1 | /* libTiMidity is licensed under the terms of the GNU Lesser General 2 | * Public License: see COPYING for details. 3 | * 4 | * Note that the included TiMidity source, based on timidity-0.2i, was 5 | * originally licensed under the GPL, but the author extended it so it 6 | * can also be used separately under the GNU LGPL or the Perl Artistic 7 | * License: see the notice by Tuukka Toivonen as it appears on the web 8 | * at http://ieee.uwaterloo.ca/sca/www.cgs.fi/tt/timidity/ . 9 | */ 10 | 11 | /* 12 | * TiMidity -- Experimental MIDI to WAVE converter 13 | * Copyright (C) 1995 Tuukka Toivonen 14 | * 15 | * This program is free software; you can redistribute it and/or modify 16 | * it under the terms of the GNU General Public License as published by 17 | * the Free Software Foundation; either version 2 of the License, or (at 18 | * your option) any later version. 19 | * 20 | * This program is distributed in the hope that it will be useful, but 21 | * WITHOUT ANY WARRANTY; without even the implied warranty of 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 23 | * 24 | * See the GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License along 27 | * with this program; if not, write to the Free Software Foundation, Inc., 28 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 29 | */ 30 | 31 | #ifdef HAVE_CONFIG_H 32 | #include "config.h" 33 | #endif 34 | 35 | #ifdef HAVE_SYS_PARAM_H 36 | #include 37 | #endif 38 | 39 | #include 40 | #include 41 | #include 42 | 43 | /* I guess "rb" should be right for any libc */ 44 | #define OPEN_MODE "rb" 45 | 46 | #include "timidity_internal.h" 47 | #include "common.h" 48 | #include "ospaths.h" 49 | 50 | /* The paths in this list will be tried by timi_openfile() */ 51 | struct _PathList { 52 | char *path; 53 | struct _PathList *next; 54 | }; 55 | 56 | static PathList *pathlist = NULL; 57 | 58 | /* This is meant to find and open files for reading */ 59 | FILE *timi_openfile(const char *name) 60 | { 61 | FILE *fp; 62 | 63 | if (!name || !*name) { 64 | DEBUG_MSG("Attempted to open nameless file.\n"); 65 | return NULL; 66 | } 67 | 68 | /* First try the given name */ 69 | DEBUG_MSG("Trying to open %s\n", name); 70 | if ((fp = fopen(name, OPEN_MODE)) != NULL) 71 | return fp; 72 | 73 | if (!is_abspath(name)) { 74 | char current_filename[TIM_MAXPATH]; 75 | PathList *plp = pathlist; 76 | char *p; 77 | size_t l; 78 | 79 | while (plp) { /* Try along the path then */ 80 | *current_filename = 0; 81 | p = current_filename; 82 | l = strlen(plp->path); 83 | if (l >= sizeof(current_filename) - 3) l = 0; 84 | if (l != 0) { 85 | memcpy(current_filename, plp->path, l); 86 | p += l; 87 | if (!is_dirsep(p[-1])) { 88 | *p++ = CHAR_DIRSEP; 89 | l++; 90 | } 91 | } 92 | timi_strxcpy(p, name, sizeof(current_filename) - l); 93 | DEBUG_MSG("Trying to open %s\n", current_filename); 94 | if ((fp = fopen(current_filename, OPEN_MODE)) != NULL) 95 | return fp; 96 | plp = plp->next; 97 | } 98 | } 99 | 100 | /* Nothing could be opened */ 101 | DEBUG_MSG("Could not open %s\n", name); 102 | return NULL; 103 | } 104 | 105 | /* This adds a directory to the path list */ 106 | int timi_add_pathlist(const char *s, size_t l) 107 | { 108 | PathList *plp = (PathList *) timi_malloc(sizeof(PathList)); 109 | if (!plp) return -2; 110 | plp->path = (char *) timi_malloc(l + 1); 111 | if (!plp->path) { 112 | timi_free (plp); 113 | return -2; 114 | } 115 | plp->next = pathlist; 116 | pathlist = plp; 117 | memcpy(plp->path, s, l); 118 | plp->path[l] = 0; 119 | return 0; 120 | } 121 | 122 | void timi_free_pathlist(void) 123 | { 124 | PathList *plp = pathlist; 125 | PathList *next; 126 | 127 | while (plp) { 128 | next = plp->next; 129 | timi_free(plp->path); 130 | timi_free(plp); 131 | plp = next; 132 | } 133 | pathlist = NULL; 134 | } 135 | 136 | /* returns the number of chars written, including NULL */ 137 | /* see: https://github.com/attractivechaos/strxcpy.git */ 138 | size_t timi_strxcpy(char *dst, const char *src, size_t size) 139 | { 140 | if (size) { 141 | size_t i = 0; 142 | size--; 143 | for (; i < size && src[i]; ++i) { 144 | dst[i] = src[i]; 145 | } 146 | dst[i] = 0; 147 | return ++i; 148 | } 149 | return 0; 150 | } 151 | 152 | /* Taken from PDClib at https://github.com/DevSolar/pdclib.git 153 | * licensed under 'CC0': 154 | * https://creativecommons.org/publicdomain/zero/1.0/legalcode 155 | */ 156 | char *timi_strtokr(char *s1, const char *s2, char **ptr) 157 | { 158 | const char *p = s2; 159 | 160 | if (!s2 || !ptr || (!s1 && !*ptr)) return NULL; 161 | 162 | if (s1 != NULL) { /* new string */ 163 | *ptr = s1; 164 | } else { /* old string continued */ 165 | if (*ptr == NULL) { 166 | /* No old string, no new string, nothing to do */ 167 | return NULL; 168 | } 169 | s1 = *ptr; 170 | } 171 | 172 | /* skip leading s2 characters */ 173 | while (*p && *s1) { 174 | if (*s1 == *p) { 175 | /* found separator; skip and start over */ 176 | ++s1; 177 | p = s2; 178 | continue; 179 | } 180 | ++p; 181 | } 182 | 183 | if (! *s1) { /* no more to parse */ 184 | *ptr = s1; 185 | return NULL; 186 | } 187 | 188 | /* skipping non-s2 characters */ 189 | *ptr = s1; 190 | while (**ptr) { 191 | p = s2; 192 | while (*p) { 193 | if (**ptr == *p++) { 194 | /* found separator; overwrite with '\0', position *ptr, return */ 195 | *((*ptr)++) = '\0'; 196 | return s1; 197 | } 198 | } 199 | ++(*ptr); 200 | } 201 | 202 | /* parsed to end of string */ 203 | return s1; 204 | } 205 | -------------------------------------------------------------------------------- /src/common.h: -------------------------------------------------------------------------------- 1 | /* libTiMidity is licensed under the terms of the GNU Lesser General 2 | * Public License: see COPYING for details. 3 | * 4 | * Note that the included TiMidity source, based on timidity-0.2i, was 5 | * originally licensed under the GPL, but the author extended it so it 6 | * can also be used separately under the GNU LGPL or the Perl Artistic 7 | * License: see the notice by Tuukka Toivonen as it appears on the web 8 | * at http://ieee.uwaterloo.ca/sca/www.cgs.fi/tt/timidity/ . 9 | */ 10 | 11 | /* 12 | * TiMidity -- Experimental MIDI to WAVE converter 13 | * Copyright (C) 1995 Tuukka Toivonen 14 | * 15 | * This program is free software; you can redistribute it and/or modify 16 | * it under the terms of the GNU General Public License as published by 17 | * the Free Software Foundation; either version 2 of the License, or (at 18 | * your option) any later version. 19 | * 20 | * This program is distributed in the hope that it will be useful, but 21 | * WITHOUT ANY WARRANTY; without even the implied warranty of 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 23 | * 24 | * See the GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License along 27 | * with this program; if not, write to the Free Software Foundation, Inc., 28 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 29 | */ 30 | 31 | #ifndef TIMIDITY_COMMON_H 32 | #define TIMIDITY_COMMON_H 33 | 34 | extern FILE *timi_openfile(const char *name); 35 | 36 | /* pathlist funcs only to be used during mid_init/mid_exit */ 37 | typedef struct _PathList PathList; 38 | extern int timi_add_pathlist(const char *s, size_t len); 39 | extern void timi_free_pathlist(void); 40 | 41 | /* in case someone wants to compile with a different malloc() than stdlib */ 42 | #define timi_malloc malloc 43 | #define timi_calloc calloc 44 | #define timi_realloc realloc 45 | #define timi_free free 46 | 47 | /* timi_strtokr() is a strtok_r() replacement */ 48 | char *timi_strtokr(char *s1, const char *s2, char **ptr); 49 | 50 | /* returns the number of chars written, including NULL */ 51 | size_t timi_strxcpy(char *dst, const char *src, size_t size); 52 | 53 | #endif /* TIMIDITY_COMMON_H */ 54 | -------------------------------------------------------------------------------- /src/instrum.h: -------------------------------------------------------------------------------- 1 | /* libTiMidity is licensed under the terms of the GNU Lesser General 2 | * Public License: see COPYING for details. 3 | * 4 | * Note that the included TiMidity source, based on timidity-0.2i, was 5 | * originally licensed under the GPL, but the author extended it so it 6 | * can also be used separately under the GNU LGPL or the Perl Artistic 7 | * License: see the notice by Tuukka Toivonen as it appears on the web 8 | * at http://ieee.uwaterloo.ca/sca/www.cgs.fi/tt/timidity/ . 9 | */ 10 | 11 | /* 12 | * TiMidity -- Experimental MIDI to WAVE converter 13 | * Copyright (C) 1995 Tuukka Toivonen 14 | * 15 | * This program is free software; you can redistribute it and/or modify 16 | * it under the terms of the GNU General Public License as published by 17 | * the Free Software Foundation; either version 2 of the License, or (at 18 | * your option) any later version. 19 | * 20 | * This program is distributed in the hope that it will be useful, but 21 | * WITHOUT ANY WARRANTY; without even the implied warranty of 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 23 | * 24 | * See the GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License along 27 | * with this program; if not, write to the Free Software Foundation, Inc., 28 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 29 | */ 30 | 31 | #ifndef TIMIDITY_INSTRUM_H 32 | #define TIMIDITY_INSTRUM_H 33 | 34 | /* Bits in modes: */ 35 | #define MODES_16BIT (1<<0) 36 | #define MODES_UNSIGNED (1<<1) 37 | #define MODES_LOOPING (1<<2) 38 | #define MODES_PINGPONG (1<<3) 39 | #define MODES_REVERSE (1<<4) 40 | #define MODES_SUSTAIN (1<<5) 41 | #define MODES_ENVELOPE (1<<6) 42 | 43 | /* A hack to delay instrument loading until after reading the 44 | entire MIDI file. */ 45 | #define MAGIC_LOAD_INSTRUMENT ((MidInstrument *)(-1)) 46 | 47 | #define SPECIAL_PROGRAM -1 48 | 49 | #define load_missing_instruments TIMI_NAMESPACE(load_missing_instruments) 50 | #define free_instruments TIMI_NAMESPACE(free_instruments) 51 | #define set_default_instrument TIMI_NAMESPACE(set_default_instrument) 52 | 53 | extern int load_missing_instruments(MidSong *song); 54 | extern void free_instruments(MidSong *song); 55 | extern int set_default_instrument(MidSong *song, const char *name); 56 | 57 | #endif /* TIMIDITY_INSTRUM_H */ 58 | -------------------------------------------------------------------------------- /src/mix.c: -------------------------------------------------------------------------------- 1 | /* libTiMidity is licensed under the terms of the GNU Lesser General 2 | * Public License: see COPYING for details. 3 | * 4 | * Note that the included TiMidity source, based on timidity-0.2i, was 5 | * originally licensed under the GPL, but the author extended it so it 6 | * can also be used separately under the GNU LGPL or the Perl Artistic 7 | * License: see the notice by Tuukka Toivonen as it appears on the web 8 | * at http://ieee.uwaterloo.ca/sca/www.cgs.fi/tt/timidity/ . 9 | */ 10 | 11 | /* 12 | * TiMidity -- Experimental MIDI to WAVE converter 13 | * Copyright (C) 1995 Tuukka Toivonen 14 | * 15 | * Suddenly, you realize that this program is free software; you get 16 | * an overwhelming urge to redistribute it and/or modify it under the 17 | * terms of the GNU General Public License as published by the Free 18 | * Software Foundation; either version 2 of the License, or (at your 19 | * option) any later version. 20 | * 21 | * This program is distributed in the hope that it will be useful, 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | * GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License along 27 | * with this program; if not, write to the Free Software Foundation, Inc., 28 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 29 | * I bet they'll be amazed. 30 | */ 31 | 32 | #ifdef HAVE_CONFIG_H 33 | #include "config.h" 34 | #endif 35 | 36 | #include 37 | #include 38 | #include 39 | 40 | #include "timidity_internal.h" 41 | #include "instrum.h" 42 | #include "playmidi.h" 43 | #include "output.h" 44 | #include "tables.h" 45 | #include "resample.h" 46 | #include "mix.h" 47 | 48 | /* Returns 1 if envelope runs out */ 49 | int recompute_envelope(MidSong *song, int v) 50 | { 51 | int stage; 52 | 53 | stage = song->voice[v].envelope_stage; 54 | 55 | if (stage>5) 56 | { 57 | /* Envelope ran out. */ 58 | song->voice[v].status = VOICE_FREE; 59 | return 1; 60 | } 61 | 62 | if (song->voice[v].sample->modes & MODES_ENVELOPE) 63 | { 64 | if (song->voice[v].status==VOICE_ON || song->voice[v].status==VOICE_SUSTAINED) 65 | { 66 | if (stage>2) 67 | { 68 | /* Freeze envelope until note turns off. Trumpets want this. */ 69 | song->voice[v].envelope_increment=0; 70 | return 0; 71 | } 72 | } 73 | } 74 | song->voice[v].envelope_stage=stage+1; 75 | 76 | if (song->voice[v].envelope_volume==song->voice[v].sample->envelope_offset[stage] || 77 | (stage > 2 && song->voice[v].envelope_volume < 78 | song->voice[v].sample->envelope_offset[stage])) 79 | return recompute_envelope(song, v); 80 | song->voice[v].envelope_target = song->voice[v].sample->envelope_offset[stage]; 81 | song->voice[v].envelope_increment = song->voice[v].sample->envelope_rate[stage]; 82 | if (song->voice[v].envelope_target < song->voice[v].envelope_volume) 83 | song->voice[v].envelope_increment = -song->voice[v].envelope_increment; 84 | return 0; 85 | } 86 | 87 | void apply_envelope_to_amp(MidSong *song, int v) 88 | { 89 | float lamp = song->voice[v].left_amp, ramp; 90 | sint32 la,ra; 91 | if (song->voice[v].panned == PANNED_MYSTERY) 92 | { 93 | ramp = song->voice[v].right_amp; 94 | if (song->voice[v].tremolo_phase_increment) 95 | { 96 | lamp *= song->voice[v].tremolo_volume; 97 | ramp *= song->voice[v].tremolo_volume; 98 | } 99 | if (song->voice[v].sample->modes & MODES_ENVELOPE) 100 | { 101 | lamp *= (float)vol_table[song->voice[v].envelope_volume>>23]; 102 | ramp *= (float)vol_table[song->voice[v].envelope_volume>>23]; 103 | } 104 | 105 | la = (sint32)TIM_FSCALE(lamp,AMP_BITS); 106 | 107 | if (la>MAX_AMP_VALUE) 108 | la=MAX_AMP_VALUE; 109 | 110 | ra = (sint32)TIM_FSCALE(ramp,AMP_BITS); 111 | if (ra>MAX_AMP_VALUE) 112 | ra=MAX_AMP_VALUE; 113 | 114 | song->voice[v].left_mix = la; 115 | song->voice[v].right_mix = ra; 116 | } 117 | else 118 | { 119 | if (song->voice[v].tremolo_phase_increment) 120 | lamp *= song->voice[v].tremolo_volume; 121 | if (song->voice[v].sample->modes & MODES_ENVELOPE) 122 | lamp *= (float)vol_table[song->voice[v].envelope_volume>>23]; 123 | 124 | la = (sint32)TIM_FSCALE(lamp,AMP_BITS); 125 | 126 | if (la>MAX_AMP_VALUE) 127 | la=MAX_AMP_VALUE; 128 | 129 | song->voice[v].left_mix = la; 130 | } 131 | } 132 | 133 | static int update_envelope(MidSong *song, int v) 134 | { 135 | song->voice[v].envelope_volume += song->voice[v].envelope_increment; 136 | /* Why is there no ^^ operator?? */ 137 | if (((song->voice[v].envelope_increment < 0) && 138 | (song->voice[v].envelope_volume <= song->voice[v].envelope_target)) || 139 | ((song->voice[v].envelope_increment > 0) && 140 | (song->voice[v].envelope_volume >= song->voice[v].envelope_target))) 141 | { 142 | song->voice[v].envelope_volume = song->voice[v].envelope_target; 143 | if (recompute_envelope(song, v)) 144 | return 1; 145 | } 146 | return 0; 147 | } 148 | 149 | static void update_tremolo(MidSong *song, int v) 150 | { 151 | sint32 depth = song->voice[v].sample->tremolo_depth << 7; 152 | 153 | if (song->voice[v].tremolo_sweep) 154 | { 155 | /* Update sweep position */ 156 | song->voice[v].tremolo_sweep_position += song->voice[v].tremolo_sweep; 157 | if (song->voice[v].tremolo_sweep_position >= (1 << SWEEP_SHIFT)) 158 | song->voice[v].tremolo_sweep=0; /* Swept to max amplitude */ 159 | else 160 | { 161 | /* Need to adjust depth */ 162 | depth *= song->voice[v].tremolo_sweep_position; 163 | depth >>= SWEEP_SHIFT; 164 | } 165 | } 166 | 167 | song->voice[v].tremolo_phase += song->voice[v].tremolo_phase_increment; 168 | 169 | /* if (song->voice[v].tremolo_phase >= (SINE_CYCLE_LENGTH<voice[v].tremolo_phase -= SINE_CYCLE_LENGTH<voice[v].tremolo_volume = (float) 173 | (1.0 - TIM_FSCALENEG((timi_sine(song->voice[v].tremolo_phase >> RATE_SHIFT) + 1.0) 174 | * depth * TREMOLO_AMPLITUDE_TUNING, 175 | 17)); 176 | 177 | /* I'm not sure about the +1.0 there -- it makes tremoloed voices' 178 | volumes on average the lower the higher the tremolo amplitude. */ 179 | } 180 | 181 | /* Returns 1 if the note died */ 182 | static int update_signal(MidSong *song, int v) 183 | { 184 | if (song->voice[v].envelope_increment && update_envelope(song, v)) 185 | return 1; 186 | 187 | if (song->voice[v].tremolo_phase_increment) 188 | update_tremolo(song, v); 189 | 190 | apply_envelope_to_amp(song, v); 191 | return 0; 192 | } 193 | 194 | #define MIXATION(a) *lp++ += (a)*s; 195 | 196 | static void mix_mystery_signal(MidSong *song, sample_t *sp, sint32 *lp, int v, 197 | int count) 198 | { 199 | MidVoice *vp = song->voice + v; 200 | final_volume_t 201 | left=vp->left_mix, 202 | right=vp->right_mix; 203 | int cc; 204 | sample_t s; 205 | 206 | if (!(cc = vp->control_counter)) 207 | { 208 | cc = song->control_ratio; 209 | if (update_signal(song, v)) 210 | return; /* Envelope ran out */ 211 | left = vp->left_mix; 212 | right = vp->right_mix; 213 | } 214 | 215 | while (count) 216 | if (cc < count) 217 | { 218 | count -= cc; 219 | while (cc--) 220 | { 221 | s = *sp++; 222 | MIXATION(left); 223 | MIXATION(right); 224 | } 225 | cc = song->control_ratio; 226 | if (update_signal(song, v)) 227 | return; /* Envelope ran out */ 228 | left = vp->left_mix; 229 | right = vp->right_mix; 230 | } 231 | else 232 | { 233 | vp->control_counter = cc - count; 234 | while (count--) 235 | { 236 | s = *sp++; 237 | MIXATION(left); 238 | MIXATION(right); 239 | } 240 | return; 241 | } 242 | } 243 | 244 | static void mix_center_signal(MidSong *song, sample_t *sp, sint32 *lp, int v, 245 | int count) 246 | { 247 | MidVoice *vp = song->voice + v; 248 | final_volume_t 249 | left=vp->left_mix; 250 | int cc; 251 | sample_t s; 252 | 253 | if (!(cc = vp->control_counter)) 254 | { 255 | cc = song->control_ratio; 256 | if (update_signal(song, v)) 257 | return; /* Envelope ran out */ 258 | left = vp->left_mix; 259 | } 260 | 261 | while (count) 262 | if (cc < count) 263 | { 264 | count -= cc; 265 | while (cc--) 266 | { 267 | s = *sp++; 268 | MIXATION(left); 269 | MIXATION(left); 270 | } 271 | cc = song->control_ratio; 272 | if (update_signal(song, v)) 273 | return; /* Envelope ran out */ 274 | left = vp->left_mix; 275 | } 276 | else 277 | { 278 | vp->control_counter = cc - count; 279 | while (count--) 280 | { 281 | s = *sp++; 282 | MIXATION(left); 283 | MIXATION(left); 284 | } 285 | return; 286 | } 287 | } 288 | 289 | static void mix_single_signal(MidSong *song, sample_t *sp, sint32 *lp, int v, 290 | int count) 291 | { 292 | MidVoice *vp = song->voice + v; 293 | final_volume_t 294 | left=vp->left_mix; 295 | int cc; 296 | sample_t s; 297 | 298 | if (!(cc = vp->control_counter)) 299 | { 300 | cc = song->control_ratio; 301 | if (update_signal(song, v)) 302 | return; /* Envelope ran out */ 303 | left = vp->left_mix; 304 | } 305 | 306 | while (count) 307 | if (cc < count) 308 | { 309 | count -= cc; 310 | while (cc--) 311 | { 312 | s = *sp++; 313 | MIXATION(left); 314 | lp++; 315 | } 316 | cc = song->control_ratio; 317 | if (update_signal(song, v)) 318 | return; /* Envelope ran out */ 319 | left = vp->left_mix; 320 | } 321 | else 322 | { 323 | vp->control_counter = cc - count; 324 | while (count--) 325 | { 326 | s = *sp++; 327 | MIXATION(left); 328 | lp++; 329 | } 330 | return; 331 | } 332 | } 333 | 334 | static void mix_mono_signal(MidSong *song, sample_t *sp, sint32 *lp, int v, 335 | int count) 336 | { 337 | MidVoice *vp = song->voice + v; 338 | final_volume_t 339 | left=vp->left_mix; 340 | int cc; 341 | sample_t s; 342 | 343 | if (!(cc = vp->control_counter)) 344 | { 345 | cc = song->control_ratio; 346 | if (update_signal(song, v)) 347 | return; /* Envelope ran out */ 348 | left = vp->left_mix; 349 | } 350 | 351 | while (count) 352 | if (cc < count) 353 | { 354 | count -= cc; 355 | while (cc--) 356 | { 357 | s = *sp++; 358 | MIXATION(left); 359 | } 360 | cc = song->control_ratio; 361 | if (update_signal(song, v)) 362 | return; /* Envelope ran out */ 363 | left = vp->left_mix; 364 | } 365 | else 366 | { 367 | vp->control_counter = cc - count; 368 | while (count--) 369 | { 370 | s = *sp++; 371 | MIXATION(left); 372 | } 373 | return; 374 | } 375 | } 376 | 377 | static void mix_mystery(MidSong *song, sample_t *sp, sint32 *lp, int v, int count) 378 | { 379 | final_volume_t 380 | left = song->voice[v].left_mix, 381 | right = song->voice[v].right_mix; 382 | sample_t s; 383 | 384 | while (count--) 385 | { 386 | s = *sp++; 387 | MIXATION(left); 388 | MIXATION(right); 389 | } 390 | } 391 | 392 | static void mix_center(MidSong *song, sample_t *sp, sint32 *lp, int v, int count) 393 | { 394 | final_volume_t 395 | left = song->voice[v].left_mix; 396 | sample_t s; 397 | 398 | while (count--) 399 | { 400 | s = *sp++; 401 | MIXATION(left); 402 | MIXATION(left); 403 | } 404 | } 405 | 406 | static void mix_single(MidSong *song, sample_t *sp, sint32 *lp, int v, int count) 407 | { 408 | final_volume_t 409 | left = song->voice[v].left_mix; 410 | sample_t s; 411 | 412 | while (count--) 413 | { 414 | s = *sp++; 415 | MIXATION(left); 416 | lp++; 417 | } 418 | } 419 | 420 | static void mix_mono(MidSong *song, sample_t *sp, sint32 *lp, int v, int count) 421 | { 422 | final_volume_t 423 | left = song->voice[v].left_mix; 424 | sample_t s; 425 | 426 | while (count--) 427 | { 428 | s = *sp++; 429 | MIXATION(left); 430 | } 431 | } 432 | 433 | /* Ramp a note out in c samples */ 434 | static void ramp_out(MidSong *song, sample_t *sp, sint32 *lp, int v, sint32 c) 435 | { 436 | /* should be final_volume_t, but uint8 gives trouble. */ 437 | sint32 left, right, li, ri; 438 | 439 | sample_t s=0; /* silly warning about uninitialized s */ 440 | 441 | left=song->voice[v].left_mix; 442 | li=-(left/c); 443 | if (!li) li=-1; 444 | 445 | /* printf("Ramping out: left=%d, c=%d, li=%d\n", left, c, li); */ 446 | 447 | if (!(song->encoding & PE_MONO)) 448 | { 449 | if (song->voice[v].panned==PANNED_MYSTERY) 450 | { 451 | right=song->voice[v].right_mix; 452 | ri=-(right/c); 453 | while (c--) 454 | { 455 | left += li; 456 | if (left<0) 457 | left=0; 458 | right += ri; 459 | if (right<0) 460 | right=0; 461 | s=*sp++; 462 | MIXATION(left); 463 | MIXATION(right); 464 | } 465 | } 466 | else if (song->voice[v].panned==PANNED_CENTER) 467 | { 468 | while (c--) 469 | { 470 | left += li; 471 | if (left<0) 472 | return; 473 | s=*sp++; 474 | MIXATION(left); 475 | MIXATION(left); 476 | } 477 | } 478 | else if (song->voice[v].panned==PANNED_LEFT) 479 | { 480 | while (c--) 481 | { 482 | left += li; 483 | if (left<0) 484 | return; 485 | s=*sp++; 486 | MIXATION(left); 487 | lp++; 488 | } 489 | } 490 | else if (song->voice[v].panned==PANNED_RIGHT) 491 | { 492 | while (c--) 493 | { 494 | left += li; 495 | if (left<0) 496 | return; 497 | s=*sp++; 498 | lp++; 499 | MIXATION(left); 500 | } 501 | } 502 | } 503 | else 504 | { 505 | /* Mono output. */ 506 | while (c--) 507 | { 508 | left += li; 509 | if (left<0) 510 | return; 511 | s=*sp++; 512 | MIXATION(left); 513 | } 514 | } 515 | } 516 | 517 | 518 | /**************** interface function ******************/ 519 | 520 | void mix_voice(MidSong *song, sint32 *buf, int v, sint32 c) 521 | { 522 | MidVoice *vp = song->voice + v; 523 | sample_t *sp; 524 | if (vp->status==VOICE_DIE) 525 | { 526 | if (c>=MAX_DIE_TIME) 527 | c=MAX_DIE_TIME; 528 | sp=resample_voice(song, v, &c); 529 | if(c > 0) 530 | ramp_out(song, sp, buf, v, c); 531 | vp->status=VOICE_FREE; 532 | } 533 | else 534 | { 535 | sp=resample_voice(song, v, &c); 536 | if (song->encoding & PE_MONO) 537 | { 538 | /* Mono output. */ 539 | if (vp->envelope_increment || vp->tremolo_phase_increment) 540 | mix_mono_signal(song, sp, buf, v, c); 541 | else 542 | mix_mono(song, sp, buf, v, c); 543 | } 544 | else 545 | { 546 | if (vp->panned == PANNED_MYSTERY) 547 | { 548 | if (vp->envelope_increment || vp->tremolo_phase_increment) 549 | mix_mystery_signal(song, sp, buf, v, c); 550 | else 551 | mix_mystery(song, sp, buf, v, c); 552 | } 553 | else if (vp->panned == PANNED_CENTER) 554 | { 555 | if (vp->envelope_increment || vp->tremolo_phase_increment) 556 | mix_center_signal(song, sp, buf, v, c); 557 | else 558 | mix_center(song, sp, buf, v, c); 559 | } 560 | else 561 | { 562 | /* It's either full left or full right. In either case, 563 | every other sample is 0. Just get the offset right: */ 564 | if (vp->panned == PANNED_RIGHT) buf++; 565 | 566 | if (vp->envelope_increment || vp->tremolo_phase_increment) 567 | mix_single_signal(song, sp, buf, v, c); 568 | else 569 | mix_single(song, sp, buf, v, c); 570 | } 571 | } 572 | } 573 | } 574 | 575 | -------------------------------------------------------------------------------- /src/mix.h: -------------------------------------------------------------------------------- 1 | /* libTiMidity is licensed under the terms of the GNU Lesser General 2 | * Public License: see COPYING for details. 3 | * 4 | * Note that the included TiMidity source, based on timidity-0.2i, was 5 | * originally licensed under the GPL, but the author extended it so it 6 | * can also be used separately under the GNU LGPL or the Perl Artistic 7 | * License: see the notice by Tuukka Toivonen as it appears on the web 8 | * at http://ieee.uwaterloo.ca/sca/www.cgs.fi/tt/timidity/ . 9 | */ 10 | 11 | /* 12 | * TiMidity -- Experimental MIDI to WAVE converter 13 | * Copyright (C) 1995 Tuukka Toivonen 14 | * 15 | * In case you haven't heard, this program is free software; 16 | * you can redistribute it and/or modify it under the terms of the 17 | * GNU General Public License as published by the Free Software 18 | * Foundation; either version 2 of the License, or (at your option) 19 | * any later version. 20 | * 21 | * This program is distributed in the hope that it will be useful, 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | * GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License along 27 | * with this program; if not, write to the Free Software Foundation, Inc., 28 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 29 | */ 30 | 31 | #ifndef TIMIDITY_MIX_H 32 | #define TIMIDITY_MIX_H 33 | 34 | #define mix_voice TIMI_NAMESPACE(mix_voice) 35 | #define recompute_envelope TIMI_NAMESPACE(recompute_envelope) 36 | #define apply_envelope_to_amp TIMI_NAMESPACE(apply_envelope_to_amp) 37 | 38 | extern void mix_voice(MidSong *song, sint32 *buf, int v, sint32 c); 39 | extern int recompute_envelope(MidSong *song, int v); 40 | extern void apply_envelope_to_amp(MidSong *song, int v); 41 | 42 | #endif /* TIMIDITY_MIX_H */ 43 | -------------------------------------------------------------------------------- /src/options.h: -------------------------------------------------------------------------------- 1 | /* libTiMidity is licensed under the terms of the GNU Lesser General 2 | * Public License: see COPYING for details. 3 | * 4 | * Note that the included TiMidity source, based on timidity-0.2i, was 5 | * originally licensed under the GPL, but the author extended it so it 6 | * can also be used separately under the GNU LGPL or the Perl Artistic 7 | * License: see the notice by Tuukka Toivonen as it appears on the web 8 | * at http://ieee.uwaterloo.ca/sca/www.cgs.fi/tt/timidity/ . 9 | */ 10 | 11 | /* 12 | * TiMidity -- Experimental MIDI to WAVE converter 13 | * Copyright (C) 1995 Tuukka Toivonen 14 | * 15 | * This program is free software; you can redistribute it and/or modify 16 | * it under the terms of the GNU General Public License as published by 17 | * the Free Software Foundation; either version 2 of the License, or (at 18 | * your option) any later version. 19 | * 20 | * This program is distributed in the hope that it will be useful, but 21 | * WITHOUT ANY WARRANTY; without even the implied warranty of 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 23 | * 24 | * See the GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License along 27 | * with this program; if not, write to the Free Software Foundation, Inc., 28 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 29 | */ 30 | 31 | #ifndef TIMIDITY_OPTIONS_H 32 | #define TIMIDITY_OPTIONS_H 33 | 34 | /* When a patch file can't be opened, one of these extensions is 35 | appended to the filename and the open is tried again. 36 | */ 37 | #define PATCH_EXT_LIST { ".pat", NULL } 38 | 39 | /* Acoustic Grand Piano seems to be the usual default instrument. */ 40 | #define DEFAULT_PROGRAM 0 41 | 42 | /* 9 here is MIDI channel 10, which is the standard percussion channel. 43 | Some files (notably C:\WINDOWS\CANYON.MID) think that 16 is one too. 44 | On the other hand, some files know that 16 is not a drum channel and 45 | try to play music on it. */ 46 | #define DEFAULT_DRUMCHANNELS (1<<9) /* | (1<<15) */ 47 | 48 | /* In percent. */ 49 | #define DEFAULT_AMPLIFICATION 70 50 | 51 | /* Default polyphony */ 52 | #define DEFAULT_VOICES 32 53 | 54 | /* 1000 here will give a control ratio of 22:1 with 22 kHz output. 55 | Higher CONTROLS_PER_SECOND values allow more accurate rendering 56 | of envelopes and tremolo. The cost is CPU time. */ 57 | #define CONTROLS_PER_SECOND 1000 58 | 59 | /* Make envelopes twice as fast. Saves ~20% CPU time (notes decay 60 | faster) and sounds more like a GUS. */ 61 | #define FAST_DECAY 62 | 63 | /* A somewhat arbitrary output frequency range. */ 64 | #define MIN_OUTPUT_RATE 4000 65 | #define MAX_OUTPUT_RATE 256000 66 | 67 | /* How many bits to use for the fractional part of sample positions. 68 | This affects tonal accuracy. The entire position counter must fit 69 | in 32 bits, so with FRACTION_BITS equal to 12, the maximum size of 70 | a sample is 1048576 samples (2 megabytes in memory). The GUS gets 71 | by with just 9 bits and a little help from its friends... 72 | "The GUS does not SUCK!!!" -- a happy user :) */ 73 | #define FRACTION_BITS 12 74 | 75 | /* For some reason the sample volume is always set to maximum in all 76 | patch files. Define this for a crude adjustment that may help 77 | equalize instrument volumes. */ 78 | #define ADJUST_SAMPLE_VOLUMES 79 | 80 | /* The number of samples to use for ramping out a dying note. Affects 81 | click removal. */ 82 | #define MAX_DIE_TIME 20 83 | 84 | /* On some machines (especially PCs without math coprocessors), 85 | looking up sine values in a table will be significantly faster than 86 | computing them on the fly. Uncomment this to use lookups. */ 87 | /* #define LOOKUP_SINE */ 88 | 89 | 90 | /**************************************************************************/ 91 | /* Anything below this shouldn't need to be changed unless you're porting 92 | to a new machine with other than 32-bit, big-endian words. */ 93 | /**************************************************************************/ 94 | 95 | /* change FRACTION_BITS above, not these */ 96 | #define INTEGER_BITS (32 - FRACTION_BITS) 97 | #define INTEGER_MASK (0xFFFFFFFF << FRACTION_BITS) 98 | #define FRACTION_MASK (~ INTEGER_MASK) 99 | 100 | /* This is enforced by some computations that must fit in an int */ 101 | #define MAX_CONTROL_RATIO 255 102 | 103 | #define MAX_AMPLIFICATION 800 104 | 105 | /* The TiMidity configuration file */ 106 | #ifndef TIMIDITY_CFG 107 | #define TIMIDITY_CFG "timidity.cfg" 108 | #endif 109 | 110 | /* These affect general volume */ 111 | #define GUARD_BITS 3 112 | #define AMP_BITS (15-GUARD_BITS) 113 | 114 | #define MAX_AMP_VALUE ((1<<(AMP_BITS+1))-1) 115 | 116 | #define TIM_FSCALE(a,b) (float)((a) * (double)(1<<(b))) 117 | #define TIM_FSCALENEG(a,b) (float)((a) * (1.0L / (double)(1<<(b)))) 118 | 119 | /* Vibrato and tremolo Choices of the Day */ 120 | #define SWEEP_TUNING 38 121 | #define VIBRATO_AMPLITUDE_TUNING 1.0L 122 | #define VIBRATO_RATE_TUNING 38 123 | #define TREMOLO_AMPLITUDE_TUNING 1.0L 124 | #define TREMOLO_RATE_TUNING 38 125 | 126 | #define SWEEP_SHIFT 16 127 | #define RATE_SHIFT 5 128 | 129 | #ifndef M_PI 130 | #define M_PI 3.14159265358979323846 131 | #endif 132 | 133 | #if defined(MAXPATHLEN) /* from sys/param.h */ 134 | #define TIM_MAXPATH MAXPATHLEN 135 | #elif defined(PATH_MAX) 136 | #define TIM_MAXPATH PATH_MAX 137 | #elif defined(_WIN32) && defined(_MAX_PATH) 138 | #define TIM_MAXPATH _MAX_PATH 139 | #elif defined(_WIN32) && defined(MAX_PATH) 140 | #define TIM_MAXPATH MAX_PATH 141 | #elif defined(__OS2__) && defined(CCHMAXPATH) 142 | #define TIM_MAXPATH CCHMAXPATH 143 | #else 144 | #define TIM_MAXPATH 1024 145 | #endif 146 | 147 | #endif /* TIMIDITY_OPTIONS_H */ 148 | -------------------------------------------------------------------------------- /src/ospaths.h: -------------------------------------------------------------------------------- 1 | /* macros and inlines to manipulate path names OS-specifically in libtimidity. 2 | * written by O. Sezer using public knowledge, 3 | * put into public domain. 4 | */ 5 | 6 | #ifndef OSPATHS_H 7 | #define OSPATHS_H 8 | 9 | #include 10 | 11 | /* ---------------------- Windows, DOS, OS2: ---------------------- */ 12 | #if defined(__MSDOS__) || defined(__DOS__) || defined(__DJGPP__) || \ 13 | defined(_MSDOS) || defined(__OS2__) || defined(__EMX__) || \ 14 | defined(_WIN32) || defined(_Windows) || defined(__WINDOWS__) || \ 15 | defined(__NT__) || defined(__CYGWIN__) 16 | 17 | #if defined(__DJGPP__) 18 | #define CHAR_DIRSEP '/' 19 | #else 20 | #define CHAR_DIRSEP '\\' 21 | #endif 22 | #define is_dirsep(c) ((c) == '/' || (c) == '\\') 23 | #define is_abspath(p) ((p)[0] == '/' || (p)[0] == '\\' || ((p)[0] && (p)[1] == ':')) 24 | 25 | #ifndef __cplusplus 26 | /* FIXME: What about C:FOO ? */ 27 | static inline char *get_last_dirsep (const char *p) { 28 | char *p1 = strrchr(p, '/'); 29 | char *p2 = strrchr(p, '\\'); 30 | if (!p1) return p2; 31 | if (!p2) return p1; 32 | return (p1 > p2)? p1 : p2; 33 | } 34 | #else 35 | static inline char *get_last_dirsep (char *p) { 36 | char *p1 = strrchr(p, '/'); 37 | char *p2 = strrchr(p, '\\'); 38 | if (!p1) return p2; 39 | if (!p2) return p1; 40 | return (p1 > p2)? p1 : p2; 41 | } 42 | static inline const char *get_last_dirsep (const char *p) { 43 | const char *p1 = strrchr(p, '/'); 44 | const char *p2 = strrchr(p, '\\'); 45 | if (!p1) return p2; 46 | if (!p2) return p1; 47 | return (p1 > p2)? p1 : p2; 48 | } 49 | #endif /* C++ */ 50 | 51 | /* ----------------- AmigaOS, MorphOS, AROS, etc: ----------------- */ 52 | #elif defined(__MORPHOS__) || defined(__AROS__) || defined(AMIGAOS) || \ 53 | defined(__amigaos__) || defined(__amigaos4__) ||defined(__amigados__) || \ 54 | defined(AMIGA) || defined(_AMIGA) || defined(__AMIGA__) 55 | 56 | #define CHAR_DIRSEP '/' 57 | #define is_dirsep(c) ((c) == '/' || (c) == ':') 58 | #define is_abspath(p) ((p)[0] == '/' || (strchr((p), ':') != NULL)) 59 | 60 | #ifndef __cplusplus 61 | static inline char *get_last_dirsep (const char *p) { 62 | char *p1 = strrchr(p, '/'); 63 | if (p1) return p1; 64 | return strchr(p, ':'); 65 | } 66 | #else 67 | static inline char *get_last_dirsep (char *p) { 68 | char *p1 = strrchr(p, '/'); 69 | if (p1) return p1; 70 | return strchr(p, ':'); 71 | } 72 | static inline const char *get_last_dirsep (const char *p) { 73 | const char *p1 = strrchr(p, '/'); 74 | if (p1) return p1; 75 | return strchr(p, ':'); 76 | } 77 | #endif /* C++ */ 78 | 79 | /* ---------------------- assumed UNIX-ish : ---------------------- */ 80 | #else /* */ 81 | 82 | #define CHAR_DIRSEP '/' 83 | #define is_dirsep(c) ((c) == '/') 84 | #define is_abspath(p) ((p)[0] == '/') 85 | 86 | #ifndef __cplusplus 87 | static inline char *get_last_dirsep (const char *p) { 88 | return strrchr(p, '/'); 89 | } 90 | #else 91 | static inline char *get_last_dirsep (char *p) { 92 | return strrchr(p, '/'); 93 | } 94 | static inline const char *get_last_dirsep (const char *p) { 95 | return strrchr(p, '/'); 96 | } 97 | #endif /* C++ */ 98 | 99 | #endif 100 | 101 | #endif /* OSPATHS_H */ 102 | -------------------------------------------------------------------------------- /src/output.c: -------------------------------------------------------------------------------- 1 | /* libTiMidity is licensed under the terms of the GNU Lesser General 2 | * Public License: see COPYING for details. 3 | * 4 | * Note that the included TiMidity source, based on timidity-0.2i, was 5 | * originally licensed under the GPL, but the author extended it so it 6 | * can also be used separately under the GNU LGPL or the Perl Artistic 7 | * License: see the notice by Tuukka Toivonen as it appears on the web 8 | * at http://ieee.uwaterloo.ca/sca/www.cgs.fi/tt/timidity/ . 9 | */ 10 | 11 | /* 12 | * TiMidity -- Experimental MIDI to WAVE converter 13 | * Copyright (C) 1995 Tuukka Toivonen 14 | * 15 | * This program is free software; you can redistribute it and/or modify 16 | * it under the terms of the GNU General Public License as published by 17 | * the Free Software Foundation; either version 2 of the License, or (at 18 | * your option) any later version. 19 | * 20 | * This program is distributed in the hope that it will be useful, but 21 | * WITHOUT ANY WARRANTY; without even the implied warranty of 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 23 | * 24 | * See the GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License along 27 | * with this program; if not, write to the Free Software Foundation, Inc., 28 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 29 | * 30 | * output.c 31 | * Audio output (to file / device) functions. 32 | */ 33 | 34 | #ifdef HAVE_CONFIG_H 35 | #include "config.h" 36 | #endif 37 | 38 | #include "timidity_internal.h" 39 | #include "output.h" 40 | 41 | /*****************************************************************/ 42 | /* Some functions to convert signed 32-bit data to other formats */ 43 | 44 | void timi_s32tos8(void *dp, sint32 *lp, sint32 c) 45 | { 46 | sint8 *cp=(sint8 *)(dp); 47 | sint32 l; 48 | while (c--) 49 | { 50 | l=(*lp++)>>(32-8-GUARD_BITS); 51 | if (l>127) l=127; 52 | else if (l<-128) l=-128; 53 | *cp++ = (sint8) (l); 54 | } 55 | } 56 | 57 | void timi_s32tou8(void *dp, sint32 *lp, sint32 c) 58 | { 59 | uint8 *cp=(uint8 *)(dp); 60 | sint32 l; 61 | while (c--) 62 | { 63 | l=(*lp++)>>(32-8-GUARD_BITS); 64 | if (l>127) l=127; 65 | else if (l<-128) l=-128; 66 | *cp++ = 0x80 ^ ((uint8) l); 67 | } 68 | } 69 | 70 | void timi_s32tos16(void *dp, sint32 *lp, sint32 c) 71 | { 72 | sint16 *sp=(sint16 *)(dp); 73 | sint32 l; 74 | while (c--) 75 | { 76 | l=(*lp++)>>(32-16-GUARD_BITS); 77 | if (l > 32767) l=32767; 78 | else if (l<-32768) l=-32768; 79 | *sp++ = (sint16)(l); 80 | } 81 | } 82 | 83 | void timi_s32tou16(void *dp, sint32 *lp, sint32 c) 84 | { 85 | uint16 *sp=(uint16 *)(dp); 86 | sint32 l; 87 | while (c--) 88 | { 89 | l=(*lp++)>>(32-16-GUARD_BITS); 90 | if (l > 32767) l=32767; 91 | else if (l<-32768) l=-32768; 92 | *sp++ = 0x8000 ^ (uint16)(l); 93 | } 94 | } 95 | 96 | void timi_s32tos16x(void *dp, sint32 *lp, sint32 c) 97 | { 98 | sint16 *sp=(sint16 *)(dp); 99 | sint32 l; 100 | while (c--) 101 | { 102 | l=(*lp++)>>(32-16-GUARD_BITS); 103 | if (l > 32767) l=32767; 104 | else if (l<-32768) l=-32768; 105 | *sp++ = XCHG_SHORT((sint16)(l)); 106 | } 107 | } 108 | 109 | void timi_s32tou16x(void *dp, sint32 *lp, sint32 c) 110 | { 111 | uint16 *sp=(uint16 *)(dp); 112 | sint32 l; 113 | while (c--) 114 | { 115 | l=(*lp++)>>(32-16-GUARD_BITS); 116 | if (l > 32767) l=32767; 117 | else if (l<-32768) l=-32768; 118 | *sp++ = XCHG_SHORT(0x8000 ^ (uint16)(l)); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/output.h: -------------------------------------------------------------------------------- 1 | /* libTiMidity is licensed under the terms of the GNU Lesser General 2 | * Public License: see COPYING for details. 3 | * 4 | * Note that the included TiMidity source, based on timidity-0.2i, was 5 | * originally licensed under the GPL, but the author extended it so it 6 | * can also be used separately under the GNU LGPL or the Perl Artistic 7 | * License: see the notice by Tuukka Toivonen as it appears on the web 8 | * at http://ieee.uwaterloo.ca/sca/www.cgs.fi/tt/timidity/ . 9 | */ 10 | 11 | /* 12 | * TiMidity -- Experimental MIDI to WAVE converter 13 | * Copyright (C) 1995 Tuukka Toivonen 14 | * 15 | * This program is free software; you can redistribute it and/or modify 16 | * it under the terms of the GNU General Public License as published by 17 | * the Free Software Foundation; either version 2 of the License, or (at 18 | * your option) any later version. 19 | * 20 | * This program is distributed in the hope that it will be useful, but 21 | * WITHOUT ANY WARRANTY; without even the implied warranty of 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 23 | * 24 | * See the GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License along 27 | * with this program; if not, write to the Free Software Foundation, Inc., 28 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 29 | */ 30 | 31 | #ifndef TIMIDITY_OUTPUT_H 32 | #define TIMIDITY_OUTPUT_H 33 | 34 | /* Data format encoding bits */ 35 | 36 | #define PE_MONO 0x01 /* versus stereo */ 37 | #define PE_SIGNED 0x02 /* versus unsigned */ 38 | #define PE_16BIT 0x04 /* versus 8-bit */ 39 | 40 | /* Conversion functions -- These overwrite the sint32 data in *lp with 41 | data in another format */ 42 | 43 | /* 8-bit signed and unsigned*/ 44 | extern void timi_s32tos8(void *dp, sint32 *lp, sint32 c); 45 | extern void timi_s32tou8(void *dp, sint32 *lp, sint32 c); 46 | 47 | /* 16-bit */ 48 | extern void timi_s32tos16(void *dp, sint32 *lp, sint32 c); 49 | extern void timi_s32tou16(void *dp, sint32 *lp, sint32 c); 50 | 51 | /* byte-exchanged 16-bit */ 52 | extern void timi_s32tos16x(void *dp, sint32 *lp, sint32 c); 53 | extern void timi_s32tou16x(void *dp, sint32 *lp, sint32 c); 54 | 55 | /* little-endian and big-endian specific */ 56 | #if !defined(WORDS_BIGENDIAN) 57 | #define timi_s32tou16l timi_s32tou16 58 | #define timi_s32tou16b timi_s32tou16x 59 | #define timi_s32tos16l timi_s32tos16 60 | #define timi_s32tos16b timi_s32tos16x 61 | #else 62 | #define timi_s32tou16l timi_s32tou16x 63 | #define timi_s32tou16b timi_s32tou16 64 | #define timi_s32tos16l timi_s32tos16x 65 | #define timi_s32tos16b timi_s32tos16 66 | #endif 67 | 68 | #endif /* TIMIDITY_OUTPUT_H */ 69 | -------------------------------------------------------------------------------- /src/playmidi.h: -------------------------------------------------------------------------------- 1 | /* libTiMidity is licensed under the terms of the GNU Lesser General 2 | * Public License: see COPYING for details. 3 | * 4 | * Note that the included TiMidity source, based on timidity-0.2i, was 5 | * originally licensed under the GPL, but the author extended it so it 6 | * can also be used separately under the GNU LGPL or the Perl Artistic 7 | * License: see the notice by Tuukka Toivonen as it appears on the web 8 | * at http://ieee.uwaterloo.ca/sca/www.cgs.fi/tt/timidity/ . 9 | */ 10 | 11 | /* 12 | * TiMidity -- Experimental MIDI to WAVE converter 13 | * Copyright (C) 1995 Tuukka Toivonen 14 | * 15 | * This program is free software; you can redistribute it and/or modify 16 | * it under the terms of the GNU General Public License as published by 17 | * the Free Software Foundation; either version 2 of the License, or (at 18 | * your option) any later version. 19 | * 20 | * This program is distributed in the hope that it will be useful, but 21 | * WITHOUT ANY WARRANTY; without even the implied warranty of 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 23 | * 24 | * See the GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License along 27 | * with this program; if not, write to the Free Software Foundation, Inc., 28 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 29 | */ 30 | 31 | #ifndef TIMIDITY_PLAYMIDI_H 32 | #define TIMIDITY_PLAYMIDI_H 33 | 34 | /* Midi events */ 35 | #define ME_NONE 0 36 | #define ME_NOTEON 1 37 | #define ME_NOTEOFF 2 38 | #define ME_KEYPRESSURE 3 39 | #define ME_MAINVOLUME 4 40 | #define ME_PAN 5 41 | #define ME_SUSTAIN 6 42 | #define ME_EXPRESSION 7 43 | #define ME_PITCHWHEEL 8 44 | #define ME_PROGRAM 9 45 | #define ME_TEMPO 10 46 | #define ME_PITCH_SENS 11 47 | 48 | #define ME_ALL_SOUNDS_OFF 12 49 | #define ME_RESET_CONTROLLERS 13 50 | #define ME_ALL_NOTES_OFF 14 51 | #define ME_TONE_BANK 15 52 | 53 | #define ME_LYRIC 16 54 | 55 | #define ME_EOT 99 56 | 57 | /* Causes the instrument's default panning to be used. */ 58 | #define NO_PANNING -1 59 | 60 | /* Voice status options: */ 61 | #define VOICE_FREE 0 62 | #define VOICE_ON 1 63 | #define VOICE_SUSTAINED 2 64 | #define VOICE_OFF 3 65 | #define VOICE_DIE 4 66 | 67 | /* Voice panned options: */ 68 | #define PANNED_MYSTERY 0 69 | #define PANNED_LEFT 1 70 | #define PANNED_RIGHT 2 71 | #define PANNED_CENTER 3 72 | /* Anything but PANNED_MYSTERY only uses the left volume */ 73 | 74 | #define ISDRUMCHANNEL(s, c) (((s)->drumchannels & (1<<(c)))) 75 | 76 | #endif /* TIMIDITY_PLAYMIDI_H */ 77 | -------------------------------------------------------------------------------- /src/readmidi.h: -------------------------------------------------------------------------------- 1 | /* libTiMidity is licensed under the terms of the GNU Lesser General 2 | * Public License: see COPYING for details. 3 | * 4 | * Note that the included TiMidity source, based on timidity-0.2i, was 5 | * originally licensed under the GPL, but the author extended it so it 6 | * can also be used separately under the GNU LGPL or the Perl Artistic 7 | * License: see the notice by Tuukka Toivonen as it appears on the web 8 | * at http://ieee.uwaterloo.ca/sca/www.cgs.fi/tt/timidity/ . 9 | */ 10 | 11 | /* 12 | * TiMidity -- Experimental MIDI to WAVE converter 13 | * Copyright (C) 1995 Tuukka Toivonen 14 | * 15 | * This program is free software; you can redistribute it and/or modify 16 | * it under the terms of the GNU General Public License as published by 17 | * the Free Software Foundation; either version 2 of the License, or (at 18 | * your option) any later version. 19 | * 20 | * This program is distributed in the hope that it will be useful, but 21 | * WITHOUT ANY WARRANTY; without even the implied warranty of 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 23 | * 24 | * See the GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License along 27 | * with this program; if not, write to the Free Software Foundation, Inc., 28 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 29 | */ 30 | 31 | #ifndef TIMIDITY_READMIDI_H 32 | #define TIMIDITY_READMIDI_H 33 | 34 | #define read_midi_file TIMI_NAMESPACE(read_midi_file) 35 | 36 | extern MidEvent *read_midi_file(MidIStream *stream, MidSong *song, sint32 *count, sint32 *sp); 37 | 38 | #endif /* TIMIDITY_READMIDI_H */ 39 | -------------------------------------------------------------------------------- /src/resample.c: -------------------------------------------------------------------------------- 1 | /* libTiMidity is licensed under the terms of the GNU Lesser General 2 | * Public License: see COPYING for details. 3 | * 4 | * Note that the included TiMidity source, based on timidity-0.2i, was 5 | * originally licensed under the GPL, but the author extended it so it 6 | * can also be used separately under the GNU LGPL or the Perl Artistic 7 | * License: see the notice by Tuukka Toivonen as it appears on the web 8 | * at http://ieee.uwaterloo.ca/sca/www.cgs.fi/tt/timidity/ . 9 | */ 10 | 11 | /* 12 | * TiMidity -- Experimental MIDI to WAVE converter 13 | * Copyright (C) 1995 Tuukka Toivonen 14 | * 15 | * This program is free software; you can redistribute it and/or modify 16 | * it under the terms of the GNU General Public License as published by 17 | * the Free Software Foundation; either version 2 of the License, or (at 18 | * your option) any later version. 19 | * 20 | * This program is distributed in the hope that it will be useful, but 21 | * WITHOUT ANY WARRANTY; without even the implied warranty of 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 23 | * 24 | * See the GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License along 27 | * with this program; if not, write to the Free Software Foundation, Inc., 28 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 29 | */ 30 | 31 | #ifdef HAVE_CONFIG_H 32 | #include "config.h" 33 | #endif 34 | 35 | #include 36 | #include 37 | #include 38 | 39 | #include "timidity_internal.h" 40 | #include "common.h" 41 | #include "instrum.h" 42 | #include "playmidi.h" 43 | #include "tables.h" 44 | #include "resample.h" 45 | 46 | #define PRECALC_LOOP_COUNT(start, end, incr) (((end) - (start) + (incr) - 1) / (incr)) 47 | 48 | /*************** resampling with fixed increment *****************/ 49 | 50 | static sample_t *rs_plain(MidSong *song, int v, sint32 *countptr) 51 | { 52 | /* Play sample until end, then free the voice. */ 53 | 54 | sample_t v1, v2; 55 | MidVoice 56 | *vp=&(song->voice[v]); 57 | sample_t 58 | *dest=song->resample_buffer, 59 | *src=vp->sample->data; 60 | sint32 61 | ofs=vp->sample_offset, 62 | incr=vp->sample_increment, 63 | le=vp->sample->data_length, 64 | count=*countptr; 65 | sint32 i, j; 66 | 67 | if (incr<0) incr = -incr; /* In case we're coming out of a bidir loop */ 68 | 69 | /* Precalc how many times we should go through the loop. 70 | NOTE: Assumes that incr > 0 and that ofs <= le */ 71 | i = PRECALC_LOOP_COUNT(ofs, le, incr); 72 | 73 | if (i > count) 74 | { 75 | i = count; 76 | count = 0; 77 | } 78 | else count -= i; 79 | 80 | for (j = 0; j < i; j++) 81 | { 82 | v1 = src[ofs >> FRACTION_BITS]; 83 | v2 = src[(ofs >> FRACTION_BITS)+1]; 84 | *dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS); 85 | ofs += incr; 86 | } 87 | 88 | if (ofs >= le) 89 | { 90 | if (ofs == le) 91 | *dest++ = src[(ofs>>FRACTION_BITS)-1]/2; 92 | vp->status=VOICE_FREE; 93 | *countptr-=count+1; 94 | } 95 | 96 | vp->sample_offset=ofs; /* Update offset */ 97 | return song->resample_buffer; 98 | } 99 | 100 | static sample_t *rs_loop(MidSong *song, MidVoice *vp, sint32 count) 101 | { 102 | /* Play sample until end-of-loop, skip back and continue. */ 103 | 104 | sample_t v1, v2; 105 | sint32 106 | ofs=vp->sample_offset, 107 | incr=vp->sample_increment, 108 | le=vp->sample->loop_end, 109 | ll=le - vp->sample->loop_start; 110 | sample_t 111 | *dest=song->resample_buffer, 112 | *src=vp->sample->data; 113 | sint32 i, j; 114 | 115 | while (count) 116 | { 117 | while (ofs >= le) 118 | ofs -= ll; 119 | /* Precalc how many times we should go through the loop */ 120 | i = PRECALC_LOOP_COUNT(ofs, le, incr); 121 | if (i > count) 122 | { 123 | i = count; 124 | count = 0; 125 | } 126 | else count -= i; 127 | for (j = 0; j < i; j++) 128 | { 129 | v1 = src[ofs >> FRACTION_BITS]; 130 | v2 = src[(ofs >> FRACTION_BITS)+1]; 131 | *dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS); 132 | ofs += incr; 133 | } 134 | } 135 | 136 | vp->sample_offset=ofs; /* Update offset */ 137 | return song->resample_buffer; 138 | } 139 | 140 | static sample_t *rs_bidir(MidSong *song, MidVoice *vp, sint32 count) 141 | { 142 | sample_t v1, v2; 143 | sint32 144 | ofs=vp->sample_offset, 145 | incr=vp->sample_increment, 146 | le=vp->sample->loop_end, 147 | ls=vp->sample->loop_start; 148 | sample_t 149 | *dest=song->resample_buffer, 150 | *src=vp->sample->data; 151 | sint32 152 | le2 = le<<1, 153 | ls2 = ls<<1, 154 | i, j; 155 | /* Play normally until inside the loop region */ 156 | 157 | if (incr > 0 && ofs < ls) 158 | { 159 | /* NOTE: Assumes that incr > 0, which is NOT always the case 160 | when doing bidirectional looping. I have yet to see a case 161 | where both ofs <= ls AND incr < 0, however. */ 162 | i = PRECALC_LOOP_COUNT(ofs, ls, incr); 163 | if (i > count) 164 | { 165 | i = count; 166 | count = 0; 167 | } 168 | else count -= i; 169 | for (j = 0; j < i; j++) 170 | { 171 | v1 = src[ofs >> FRACTION_BITS]; 172 | v2 = src[(ofs >> FRACTION_BITS)+1]; 173 | *dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS); 174 | ofs += incr; 175 | } 176 | } 177 | 178 | /* Then do the bidirectional looping */ 179 | while(count) 180 | { 181 | /* Precalc how many times we should go through the loop */ 182 | i = PRECALC_LOOP_COUNT(ofs, incr > 0 ? le : ls, incr); 183 | if (i > count) 184 | { 185 | i = count; 186 | count = 0; 187 | } 188 | else count -= i; 189 | for (j = 0; j < i; j++) 190 | { 191 | v1 = src[ofs >> FRACTION_BITS]; 192 | v2 = src[(ofs >> FRACTION_BITS)+1]; 193 | *dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS); 194 | ofs += incr; 195 | } 196 | if (ofs>=le) 197 | { 198 | /* fold the overshoot back in */ 199 | ofs = le2 - ofs; 200 | incr *= -1; 201 | } 202 | else if (ofs <= ls) 203 | { 204 | ofs = ls2 - ofs; 205 | incr *= -1; 206 | } 207 | } 208 | 209 | vp->sample_increment=incr; 210 | vp->sample_offset=ofs; /* Update offset */ 211 | return song->resample_buffer; 212 | } 213 | 214 | /*********************** vibrato versions ***************************/ 215 | 216 | /* We only need to compute one half of the vibrato sine cycle */ 217 | static int vib_phase_to_inc_ptr(int phase) 218 | { 219 | if (phase < MID_VIBRATO_SAMPLE_INCREMENTS/2) 220 | return MID_VIBRATO_SAMPLE_INCREMENTS/2-1-phase; 221 | else if (phase >= 3*MID_VIBRATO_SAMPLE_INCREMENTS/2) 222 | return 5*MID_VIBRATO_SAMPLE_INCREMENTS/2-1-phase; 223 | else 224 | return phase-MID_VIBRATO_SAMPLE_INCREMENTS/2; 225 | } 226 | 227 | static sint32 update_vibrato(MidSong *song, MidVoice *vp, int sign) 228 | { 229 | sint32 depth; 230 | int phase, pb; 231 | double a; 232 | 233 | if (vp->vibrato_phase++ >= 2*MID_VIBRATO_SAMPLE_INCREMENTS-1) 234 | vp->vibrato_phase=0; 235 | phase=vib_phase_to_inc_ptr(vp->vibrato_phase); 236 | 237 | if (vp->vibrato_sample_increment[phase]) 238 | { 239 | if (sign) 240 | return -vp->vibrato_sample_increment[phase]; 241 | else 242 | return vp->vibrato_sample_increment[phase]; 243 | } 244 | 245 | /* Need to compute this sample increment. */ 246 | depth=vp->sample->vibrato_depth<<7; 247 | 248 | if (vp->vibrato_sweep) 249 | { 250 | /* Need to update sweep */ 251 | vp->vibrato_sweep_position += vp->vibrato_sweep; 252 | if (vp->vibrato_sweep_position >= (1<vibrato_sweep=0; 254 | else 255 | { 256 | /* Adjust depth */ 257 | depth *= vp->vibrato_sweep_position; 258 | depth >>= SWEEP_SHIFT; 259 | } 260 | } 261 | 262 | a = TIM_FSCALE(((double)(vp->sample->sample_rate) * 263 | (double)(vp->frequency)) / 264 | ((double)(vp->sample->root_freq) * 265 | (double)(song->rate)), 266 | FRACTION_BITS); 267 | 268 | pb=(int)((timi_sine(vp->vibrato_phase * 269 | (SINE_CYCLE_LENGTH/(2*MID_VIBRATO_SAMPLE_INCREMENTS))) 270 | * (double)(depth) * VIBRATO_AMPLITUDE_TUNING)); 271 | 272 | if (pb<0) 273 | { 274 | pb=-pb; 275 | a /= bend_fine[(pb>>5) & 0xFF] * bend_coarse[pb>>13]; 276 | } 277 | else 278 | a *= bend_fine[(pb>>5) & 0xFF] * bend_coarse[pb>>13]; 279 | 280 | /* If the sweep's over, we can store the newly computed sample_increment */ 281 | if (!vp->vibrato_sweep) 282 | vp->vibrato_sample_increment[phase]=(sint32) a; 283 | 284 | if (sign) 285 | a = -a; /* need to preserve the loop direction */ 286 | 287 | return (sint32) a; 288 | } 289 | 290 | static sample_t *rs_vib_plain(MidSong *song, int v, sint32 *countptr) 291 | { 292 | /* Play sample until end, then free the voice. */ 293 | 294 | sample_t v1, v2; 295 | MidVoice *vp=&(song->voice[v]); 296 | sample_t 297 | *dest=song->resample_buffer, 298 | *src=vp->sample->data; 299 | sint32 300 | le=vp->sample->data_length, 301 | ofs=vp->sample_offset, 302 | incr=vp->sample_increment, 303 | count=*countptr; 304 | int 305 | cc=vp->vibrato_control_counter; 306 | 307 | /* This has never been tested */ 308 | 309 | if (incr<0) incr = -incr; /* In case we're coming out of a bidir loop */ 310 | 311 | while (count--) 312 | { 313 | if (!cc--) 314 | { 315 | cc=vp->vibrato_control_ratio; 316 | incr=update_vibrato(song, vp, 0); 317 | } 318 | v1 = src[ofs >> FRACTION_BITS]; 319 | v2 = src[(ofs >> FRACTION_BITS)+1]; 320 | *dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS); 321 | ofs += incr; 322 | if (ofs >= le) 323 | { 324 | if (ofs == le) 325 | *dest++ = src[(ofs>>FRACTION_BITS)-1]/2; 326 | vp->status=VOICE_FREE; 327 | *countptr-=count+1; 328 | break; 329 | } 330 | } 331 | 332 | vp->vibrato_control_counter=cc; 333 | vp->sample_increment=incr; 334 | vp->sample_offset=ofs; /* Update offset */ 335 | return song->resample_buffer; 336 | } 337 | 338 | static sample_t *rs_vib_loop(MidSong *song, MidVoice *vp, sint32 count) 339 | { 340 | /* Play sample until end-of-loop, skip back and continue. */ 341 | 342 | sample_t v1, v2; 343 | sint32 344 | ofs=vp->sample_offset, 345 | incr=vp->sample_increment, 346 | le=vp->sample->loop_end, 347 | ll=le - vp->sample->loop_start; 348 | sample_t 349 | *dest=song->resample_buffer, 350 | *src=vp->sample->data; 351 | int 352 | cc=vp->vibrato_control_counter; 353 | sint32 i, j; 354 | int 355 | vibflag=0; 356 | 357 | while (count) 358 | { 359 | /* Hopefully the loop is longer than an increment */ 360 | while(ofs >= le) 361 | ofs -= ll; 362 | /* Precalc how many times to go through the loop, taking 363 | the vibrato control ratio into account this time. */ 364 | i = PRECALC_LOOP_COUNT(ofs, le, incr); 365 | if(i > count) i = count; 366 | if(i > cc) 367 | { 368 | i = cc; 369 | vibflag = 1; 370 | } 371 | else cc -= i; 372 | count -= i; 373 | for (j = 0; j < i; j++) 374 | { 375 | v1 = src[ofs >> FRACTION_BITS]; 376 | v2 = src[(ofs >> FRACTION_BITS)+1]; 377 | *dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS); 378 | ofs += incr; 379 | } 380 | if(vibflag) 381 | { 382 | cc = vp->vibrato_control_ratio; 383 | incr = update_vibrato(song, vp, 0); 384 | vibflag = 0; 385 | } 386 | } 387 | 388 | vp->vibrato_control_counter=cc; 389 | vp->sample_increment=incr; 390 | vp->sample_offset=ofs; /* Update offset */ 391 | return song->resample_buffer; 392 | } 393 | 394 | static sample_t *rs_vib_bidir(MidSong *song, MidVoice *vp, sint32 count) 395 | { 396 | sample_t v1, v2; 397 | sint32 398 | ofs=vp->sample_offset, 399 | incr=vp->sample_increment, 400 | le=vp->sample->loop_end, 401 | ls=vp->sample->loop_start; 402 | sample_t 403 | *dest=song->resample_buffer, 404 | *src=vp->sample->data; 405 | int 406 | cc=vp->vibrato_control_counter; 407 | sint32 408 | le2=le<<1, 409 | ls2=ls<<1, 410 | i, j; 411 | int 412 | vibflag = 0; 413 | 414 | /* Play normally until inside the loop region */ 415 | while (count && incr > 0 && ofs < ls) 416 | { 417 | i = PRECALC_LOOP_COUNT(ofs, ls, incr); 418 | if (i > count) i = count; 419 | if (i > cc) 420 | { 421 | i = cc; 422 | vibflag = 1; 423 | } 424 | else cc -= i; 425 | count -= i; 426 | for (j = 0; j < i; j++) 427 | { 428 | v1 = src[ofs >> FRACTION_BITS]; 429 | v2 = src[(ofs >> FRACTION_BITS)+1]; 430 | *dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS); 431 | ofs += incr; 432 | } 433 | if (vibflag) 434 | { 435 | cc = vp->vibrato_control_ratio; 436 | incr = update_vibrato(song, vp, 0); 437 | vibflag = 0; 438 | } 439 | } 440 | 441 | /* Then do the bidirectional looping */ 442 | while (count) 443 | { 444 | /* Precalc how many times we should go through the loop */ 445 | i = PRECALC_LOOP_COUNT(ofs, incr > 0 ? le : ls, incr); 446 | if(i > count) i = count; 447 | if(i > cc) 448 | { 449 | i = cc; 450 | vibflag = 1; 451 | } 452 | else cc -= i; 453 | count -= i; 454 | while (i--) 455 | { 456 | v1 = src[ofs >> FRACTION_BITS]; 457 | v2 = src[(ofs >> FRACTION_BITS)+1]; 458 | *dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS); 459 | ofs += incr; 460 | } 461 | if (vibflag) 462 | { 463 | cc = vp->vibrato_control_ratio; 464 | incr = update_vibrato(song, vp, (incr < 0)); 465 | vibflag = 0; 466 | } 467 | if (ofs >= le) 468 | { 469 | /* fold the overshoot back in */ 470 | ofs = le2 - ofs; 471 | incr *= -1; 472 | } 473 | else if (ofs <= ls) 474 | { 475 | ofs = ls2 - ofs; 476 | incr *= -1; 477 | } 478 | } 479 | 480 | vp->vibrato_control_counter=cc; 481 | vp->sample_increment=incr; 482 | vp->sample_offset=ofs; /* Update offset */ 483 | return song->resample_buffer; 484 | } 485 | 486 | sample_t *resample_voice(MidSong *song, int v, sint32 *countptr) 487 | { 488 | sint32 ofs; 489 | uint8 modes; 490 | MidVoice *vp=&(song->voice[v]); 491 | 492 | if (!(vp->sample->sample_rate)) 493 | { 494 | /* Pre-resampled data -- just update the offset and check if 495 | we're out of data. */ 496 | ofs=vp->sample_offset >> FRACTION_BITS; /* Kind of silly to use 497 | FRACTION_BITS here... */ 498 | if (*countptr >= (vp->sample->data_length>>FRACTION_BITS) - ofs) 499 | { 500 | /* Note finished. Free the voice. */ 501 | vp->status = VOICE_FREE; 502 | 503 | /* Let the caller know how much data we had left */ 504 | *countptr = (vp->sample->data_length>>FRACTION_BITS) - ofs; 505 | } 506 | else 507 | vp->sample_offset += *countptr << FRACTION_BITS; 508 | 509 | return vp->sample->data+ofs; 510 | } 511 | 512 | /* Need to resample. Use the proper function. */ 513 | modes=vp->sample->modes; 514 | 515 | if (vp->vibrato_control_ratio) 516 | { 517 | if ((modes & MODES_LOOPING) && 518 | ((modes & MODES_ENVELOPE) || 519 | (vp->status==VOICE_ON || vp->status==VOICE_SUSTAINED))) 520 | { 521 | if (modes & MODES_PINGPONG) 522 | return rs_vib_bidir(song, vp, *countptr); 523 | else 524 | return rs_vib_loop(song, vp, *countptr); 525 | } 526 | else 527 | return rs_vib_plain(song, v, countptr); 528 | } 529 | else 530 | { 531 | if ((modes & MODES_LOOPING) && 532 | ((modes & MODES_ENVELOPE) || 533 | (vp->status==VOICE_ON || vp->status==VOICE_SUSTAINED))) 534 | { 535 | if (modes & MODES_PINGPONG) 536 | return rs_bidir(song, vp, *countptr); 537 | else 538 | return rs_loop(song, vp, *countptr); 539 | } 540 | else 541 | return rs_plain(song, v, countptr); 542 | } 543 | } 544 | 545 | void pre_resample(MidSong *song, MidSample *sp) 546 | { 547 | double a, xdiff; 548 | sint32 incr, ofs, newlen, count; 549 | sint16 *newdata, *dest, *src = (sint16 *) sp->data, *vptr; 550 | sint32 v, v1, v2, v3, v4, v5, i; 551 | #ifdef TIMIDITY_DEBUG 552 | static const char note_name[12][3] = { 553 | "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" 554 | }; 555 | #endif 556 | 557 | DEBUG_MSG(" * pre-resampling for note %d (%s%d)\n", 558 | sp->note_to_use, 559 | note_name[sp->note_to_use % 12], (sp->note_to_use & 0x7F) / 12); 560 | 561 | a = ((double) (sp->root_freq) * song->rate) / 562 | ((double) (sp->sample_rate) * freq_table[(int) (sp->note_to_use)]); 563 | if(sp->data_length * a >= 0x7fffffffL) { /* Too large to compute */ 564 | DEBUG_MSG(" *** Can't pre-resampling for note %d\n", sp->note_to_use); 565 | return; 566 | } 567 | 568 | newlen = (sint32)(sp->data_length * a); 569 | count = (newlen >> FRACTION_BITS) - 1; 570 | ofs = incr = (sp->data_length - (1 << FRACTION_BITS)) / count; 571 | 572 | if((double)newlen + incr >= 0x7fffffffL) { /* Too large to compute */ 573 | DEBUG_MSG(" *** Can't pre-resampling for note %d\n", sp->note_to_use); 574 | return; 575 | } 576 | 577 | dest = newdata = (sint16 *) timi_malloc((newlen >> (FRACTION_BITS - 1)) + 2); 578 | if(!dest) { 579 | song->oom = 1; 580 | return; 581 | } 582 | 583 | if (--count) 584 | *dest++ = src[0]; 585 | 586 | /* Since we're pre-processing and this doesn't have to be done in 587 | real-time, we go ahead and do the full sliding cubic interpolation. */ 588 | count--; 589 | for(i = 0; i < count; i++) 590 | { 591 | vptr = src + (ofs >> FRACTION_BITS); 592 | v1 = ((vptr>=src+1)? *(vptr - 1):0); 593 | v2 = *vptr; 594 | v3 = *(vptr + 1); 595 | v4 = *(vptr + 2); 596 | v5 = v2 - v3; 597 | xdiff = TIM_FSCALENEG(ofs & FRACTION_MASK, FRACTION_BITS); 598 | v = (sint32)(v2 + xdiff * (1.0/6.0) * (3 * (v3 - v5) - 2 * v1 - v4 + 599 | xdiff * (3 * (v1 - v2 - v5) + xdiff * (3 * v5 + v4 - v1)))); 600 | *dest++ = (sint16)((v > 32767) ? 32767 : ((v < -32768) ? -32768 : v)); 601 | ofs += incr; 602 | } 603 | 604 | if (ofs & FRACTION_MASK) 605 | { 606 | v1 = src[ofs >> FRACTION_BITS]; 607 | v2 = src[(ofs >> FRACTION_BITS) + 1]; 608 | *dest++ = (sint16)(v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS)); 609 | } 610 | else 611 | *dest++ = src[ofs >> FRACTION_BITS]; 612 | 613 | *dest = *(dest - 1) / 2; 614 | ++dest; 615 | *dest = *(dest - 1) / 2; 616 | 617 | sp->data_length = newlen; 618 | sp->loop_start = (sint32)(sp->loop_start * a); 619 | sp->loop_end = (sint32)(sp->loop_end * a); 620 | timi_free(sp->data); 621 | sp->data = (sample_t *) newdata; 622 | sp->sample_rate = 0; 623 | } 624 | -------------------------------------------------------------------------------- /src/resample.h: -------------------------------------------------------------------------------- 1 | /* libTiMidity is licensed under the terms of the GNU Lesser General 2 | * Public License: see COPYING for details. 3 | * 4 | * Note that the included TiMidity source, based on timidity-0.2i, was 5 | * originally licensed under the GPL, but the author extended it so it 6 | * can also be used separately under the GNU LGPL or the Perl Artistic 7 | * License: see the notice by Tuukka Toivonen as it appears on the web 8 | * at http://ieee.uwaterloo.ca/sca/www.cgs.fi/tt/timidity/ . 9 | */ 10 | 11 | /* 12 | * TiMidity -- Experimental MIDI to WAVE converter 13 | * Copyright (C) 1995 Tuukka Toivonen 14 | * 15 | * This program is free software; you can redistribute it and/or modify 16 | * it under the terms of the GNU General Public License as published by 17 | * the Free Software Foundation; either version 2 of the License, or (at 18 | * your option) any later version. 19 | * 20 | * This program is distributed in the hope that it will be useful, but 21 | * WITHOUT ANY WARRANTY; without even the implied warranty of 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 23 | * 24 | * See the GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License along 27 | * with this program; if not, write to the Free Software Foundation, Inc., 28 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 29 | */ 30 | 31 | #ifndef TIMIDITY_RESAMPLE_H 32 | #define TIMIDITY_RESAMPLE_H 33 | 34 | #define resample_voice TIMI_NAMESPACE(resample_voice) 35 | #define pre_resample TIMI_NAMESPACE(pre_resample) 36 | 37 | extern sample_t *resample_voice(MidSong *song, int v, sint32 *countptr); 38 | extern void pre_resample(MidSong *song, MidSample *sp); 39 | 40 | #endif /* TIMIDITY_RESAMPLE_H */ 41 | -------------------------------------------------------------------------------- /src/stream.c: -------------------------------------------------------------------------------- 1 | /* libTiMidity is licensed under the terms of the GNU Lesser General 2 | * Public License: see COPYING for details. 3 | * 4 | * Note that the included TiMidity source, based on timidity-0.2i, was 5 | * originally licensed under the GPL, but the author extended it so it 6 | * can also be used separately under the GNU LGPL or the Perl Artistic 7 | * License: see the notice by Tuukka Toivonen as it appears on the web 8 | * at http://ieee.uwaterloo.ca/sca/www.cgs.fi/tt/timidity/ . 9 | */ 10 | 11 | /* libTiMidity -- MIDI to WAVE converter library 12 | * Copyright (C) 2004 Konstantin Korikov 13 | * Copyright (C) 2014 O.Sezer 14 | * 15 | * This library is free software; you can redistribute it and/or modify it 16 | * under the terms of the GNU Lesser General Public License as published by 17 | * the Free Software Foundation; either version 2.1 of the License, or (at 18 | * your option) any later version. 19 | * 20 | * This library is distributed in the hope that it will be useful, but 21 | * WITHOUT ANY WARRANTY; without even the implied warranty of 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 23 | * General Public License for more details. 24 | * 25 | * You should have received a copy of the GNU Lesser General Public License 26 | * along with this library; if not, write to the Free Software Foundation, 27 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 28 | */ 29 | 30 | #ifdef HAVE_CONFIG_H 31 | #include "config.h" 32 | #endif 33 | 34 | #include "string.h" 35 | 36 | #include "timidity_internal.h" 37 | #include "common.h" 38 | 39 | struct _MidIStream 40 | { 41 | MidIStreamReadFunc read_fn; 42 | MidIStreamSeekFunc seek_fn; 43 | MidIStreamTellFunc tell_fn; 44 | MidIStreamCloseFunc close_fn; 45 | void *ctx; 46 | }; 47 | 48 | typedef struct StdIOContext 49 | { 50 | FILE *fp; 51 | int autoclose; 52 | } StdIOContext; 53 | 54 | static size_t 55 | stdio_istream_read (void *ctx, void *ptr, size_t size, size_t nmemb) 56 | { 57 | return fread (ptr, size, nmemb, ((StdIOContext *) ctx)->fp); 58 | } 59 | 60 | static int 61 | stdio_istream_seek (void *ctx, long offset, int whence) 62 | { 63 | return fseek (((StdIOContext *) ctx)->fp, offset, whence); 64 | } 65 | 66 | static long 67 | stdio_istream_tell (void *ctx) 68 | { 69 | return ftell (((StdIOContext *) ctx)->fp); 70 | } 71 | 72 | static int 73 | stdio_istream_close (void *ctx) 74 | { 75 | int ret = 0; 76 | if (((StdIOContext *) ctx)->autoclose) 77 | ret = fclose (((StdIOContext *) ctx)->fp); 78 | timi_free (ctx); 79 | return ret; 80 | } 81 | 82 | typedef struct MemContext 83 | { 84 | sint8 *base; 85 | sint8 *current; 86 | sint8 *end; 87 | } MemContext; 88 | 89 | static size_t 90 | mem_istream_read (void *ctx, void *ptr, size_t size, size_t nmemb) 91 | { 92 | MemContext *c; 93 | size_t count; 94 | 95 | c = (MemContext *) ctx; 96 | count = nmemb; 97 | 98 | if (c->current + count * size > c->end) 99 | count = (c->end - c->current) / size; 100 | 101 | if (count == 0) 102 | return 0; 103 | 104 | memcpy (ptr, c->current, count * size); 105 | c->current += count * size; 106 | 107 | return count; 108 | } 109 | 110 | static int 111 | mem_istream_seek(void *ctx, long offset, int whence) 112 | { 113 | MemContext *c = (MemContext *) ctx; 114 | 115 | switch (whence) { 116 | case SEEK_SET: 117 | break; 118 | case SEEK_CUR: 119 | offset += (c->current - c->base); 120 | break; 121 | case SEEK_END: 122 | offset += (c->end - c->base); 123 | break; 124 | default: 125 | return -1; 126 | } 127 | 128 | if (offset < 0) 129 | return -1; 130 | 131 | if (offset > c->end - c->base) /* just seek to end */ 132 | offset = c->end - c->base; 133 | 134 | c->current = c->base + offset; 135 | return 0; 136 | } 137 | 138 | static long 139 | mem_istream_tell(void *ctx) 140 | { 141 | MemContext *c = (MemContext *) ctx; 142 | return (c->current - c->base); 143 | } 144 | 145 | static int 146 | mem_istream_close (void *ctx) 147 | { 148 | timi_free (ctx); 149 | return 0; 150 | } 151 | 152 | MidIStream * 153 | mid_istream_open_fp (FILE * fp, int autoclose) 154 | { 155 | StdIOContext *ctx; 156 | MidIStream *stream; 157 | 158 | stream = (MidIStream *) timi_malloc(sizeof(MidIStream)); 159 | if (stream == NULL) 160 | return NULL; 161 | 162 | ctx = (StdIOContext *) timi_malloc(sizeof(StdIOContext)); 163 | if (ctx == NULL) 164 | { 165 | timi_free (stream); 166 | return NULL; 167 | } 168 | ctx->fp = fp; 169 | ctx->autoclose = autoclose; 170 | 171 | stream->ctx = ctx; 172 | stream->read_fn = stdio_istream_read; 173 | stream->seek_fn = stdio_istream_seek; 174 | stream->tell_fn = stdio_istream_tell; 175 | stream->close_fn = stdio_istream_close; 176 | 177 | return stream; 178 | } 179 | 180 | MidIStream * 181 | mid_istream_open_file (const char *file) 182 | { 183 | FILE *fp; 184 | 185 | fp = fopen (file, "rb"); 186 | if (fp == NULL) 187 | return NULL; 188 | 189 | return mid_istream_open_fp (fp, 1); 190 | } 191 | 192 | MidIStream * 193 | mid_istream_open_mem (void *mem, size_t size) 194 | { 195 | MemContext *ctx; 196 | MidIStream *stream; 197 | 198 | stream = (MidIStream *) timi_malloc(sizeof(MidIStream)); 199 | if (stream == NULL) 200 | return NULL; 201 | 202 | ctx = (MemContext *) timi_malloc(sizeof(MemContext)); 203 | if (ctx == NULL) 204 | { 205 | timi_free (stream); 206 | return NULL; 207 | } 208 | ctx->base = (sint8 *) mem; 209 | ctx->current = (sint8 *) mem; 210 | ctx->end = ((sint8 *) mem) + size; 211 | 212 | stream->ctx = ctx; 213 | stream->read_fn = mem_istream_read; 214 | stream->seek_fn = mem_istream_seek; 215 | stream->tell_fn = mem_istream_tell; 216 | stream->close_fn = mem_istream_close; 217 | 218 | return stream; 219 | } 220 | 221 | MidIStream * 222 | mid_istream_open_callbacks (MidIStreamReadFunc readfn, 223 | MidIStreamSeekFunc seekfn, 224 | MidIStreamTellFunc tellfn, 225 | MidIStreamCloseFunc closefn, void *context) 226 | { 227 | MidIStream *stream; 228 | 229 | stream = (MidIStream *) timi_malloc(sizeof(MidIStream)); 230 | if (stream == NULL) 231 | return NULL; 232 | 233 | stream->ctx = context; 234 | stream->read_fn = readfn; 235 | stream->seek_fn = seekfn; 236 | stream->tell_fn = tellfn; 237 | stream->close_fn = closefn; 238 | 239 | return stream; 240 | } 241 | 242 | size_t 243 | mid_istream_read (MidIStream * stream, void *ptr, size_t size, size_t nmemb) 244 | { 245 | return stream->read_fn (stream->ctx, ptr, size, nmemb); 246 | } 247 | 248 | int 249 | mid_istream_seek (MidIStream * stream, long offset, int whence) 250 | { 251 | return stream->seek_fn (stream->ctx, offset, whence); 252 | } 253 | 254 | long 255 | mid_istream_tell (MidIStream * stream) 256 | { 257 | return stream->tell_fn (stream->ctx); 258 | } 259 | 260 | int 261 | mid_istream_skip (MidIStream * stream, long len) 262 | { 263 | if (stream->seek_fn (stream->ctx, len, SEEK_CUR) < 0) 264 | return -1; 265 | return 0; 266 | } 267 | 268 | int 269 | mid_istream_close (MidIStream * stream) 270 | { 271 | int ret = stream->close_fn (stream->ctx); 272 | timi_free (stream); 273 | return ret; 274 | } 275 | -------------------------------------------------------------------------------- /src/tables.h: -------------------------------------------------------------------------------- 1 | /* libTiMidity is licensed under the terms of the GNU Lesser General 2 | * Public License: see COPYING for details. 3 | * 4 | * Note that the included TiMidity source, based on timidity-0.2i, was 5 | * originally licensed under the GPL, but the author extended it so it 6 | * can also be used separately under the GNU LGPL or the Perl Artistic 7 | * License: see the notice by Tuukka Toivonen as it appears on the web 8 | * at http://ieee.uwaterloo.ca/sca/www.cgs.fi/tt/timidity/ . 9 | */ 10 | 11 | /* 12 | * TiMidity -- Experimental MIDI to WAVE converter 13 | * Copyright (C) 1995 Tuukka Toivonen 14 | * 15 | * This program is free software; you can redistribute it and/or modify 16 | * it under the terms of the GNU General Public License as published by 17 | * the Free Software Foundation; either version 2 of the License, or (at 18 | * your option) any later version. 19 | * 20 | * This program is distributed in the hope that it will be useful, but 21 | * WITHOUT ANY WARRANTY; without even the implied warranty of 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 23 | * 24 | * See the GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License along 27 | * with this program; if not, write to the Free Software Foundation, Inc., 28 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 29 | */ 30 | 31 | #ifndef TIMIDITY_TABLES_H 32 | #define TIMIDITY_TABLES_H 33 | 34 | #ifdef LOOKUP_SINE 35 | extern float _timi_sine(int); 36 | #define timi_sine _timi_sine 37 | #else 38 | #include 39 | #define timi_sine(x) (sin((2*M_PI/1024.0) * (x))) 40 | #endif 41 | 42 | #define SINE_CYCLE_LENGTH 1024 43 | 44 | #define freq_table TIMI_NAMESPACE(freq_table) 45 | #define vol_table TIMI_NAMESPACE(vol_table) 46 | #define bend_fine TIMI_NAMESPACE(bend_fine) 47 | #define bend_coarse TIMI_NAMESPACE(bend_coarse) 48 | 49 | extern const sint32 freq_table[]; 50 | extern const double vol_table[]; 51 | extern const double bend_fine[]; 52 | extern const double bend_coarse[]; 53 | 54 | #endif /* TIMIDITY_TABLES_H */ 55 | -------------------------------------------------------------------------------- /src/timi_endian.h: -------------------------------------------------------------------------------- 1 | /* libTiMidity is licensed under the terms of the GNU Lesser General 2 | * Public License: see COPYING for details. 3 | * 4 | * Note that the included TiMidity source, based on timidity-0.2i, was 5 | * originally licensed under the GPL, but the author extended it so it 6 | * can also be used separately under the GNU LGPL or the Perl Artistic 7 | * License: see the notice by Tuukka Toivonen as it appears on the web 8 | * at http://ieee.uwaterloo.ca/sca/www.cgs.fi/tt/timidity/ . 9 | */ 10 | 11 | /* timi_endian.h -- endianness detection 12 | * Copyright (C) 2007-2016 O.Sezer 13 | * 14 | * This library is free software; you can redistribute it and/or modify it 15 | * under the terms of the GNU Lesser General Public License as published by 16 | * the Free Software Foundation; either version 2.1 of the License, or (at 17 | * your option) any later version. 18 | * 19 | * This library is distributed in the hope that it will be useful, but 20 | * WITHOUT ANY WARRANTY; without even the implied warranty of 21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 22 | * General Public License for more details. 23 | * 24 | * You should have received a copy of the GNU Lesser General Public License 25 | * along with this library; if not, write to the Free Software Foundation, 26 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 27 | */ 28 | 29 | #ifndef TIMI_ENDIAN_H 30 | #define TIMI_ENDIAN_H 31 | 32 | /* try the system headers first: with BSD and derivatives, 33 | * sys/types.h can pull in the correct header and defs. */ 34 | #if !defined __VBCC__ 35 | #include 36 | #endif 37 | 38 | #if !defined(BYTE_ORDER) /* include more if it didn't work */ 39 | 40 | # if defined(__linux__) || defined(__linux) 41 | # include 42 | # elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ 43 | defined(__FreeBSD_kernel__) /* Debian GNU/kFreeBSD */ || \ 44 | (defined(__APPLE__) && defined(__MACH__)) /* Mac OS X */ || \ 45 | defined(__DragonFly__) 46 | # include 47 | # elif defined(__sun) || defined(__svr4__) 48 | # include 49 | # elif defined(_AIX) 50 | # include 51 | # elif defined(sgi) 52 | # include 53 | # elif defined(__MINGW32__) 54 | # include 55 | # elif defined(__DJGPP__) 56 | # include 57 | # elif defined(__EMX__) 58 | # include 59 | # elif defined(__OS2__) && defined(__WATCOMC__) 60 | # include 61 | # elif defined(__MORPHOS__) 62 | # include 63 | # elif defined(__amigaos__) && defined(__NEWLIB__) 64 | # include 65 | # elif defined(__amigaos__) && defined(__CLIB2__) 66 | # include 67 | # endif 68 | 69 | #endif /* endian includes */ 70 | 71 | 72 | /* alternative macro names: */ 73 | #if defined(__BYTE_ORDER) && !defined(BYTE_ORDER) 74 | #define BYTE_ORDER __BYTE_ORDER 75 | #endif 76 | #if defined(__LITTLE_ENDIAN) && !defined(LITTLE_ENDIAN) 77 | #define LITTLE_ENDIAN __LITTLE_ENDIAN 78 | #endif 79 | #if defined(__BIG_ENDIAN) && !defined(BIG_ENDIAN) 80 | #define BIG_ENDIAN __BIG_ENDIAN 81 | #endif 82 | 83 | /* new gcc and clang versions pre-define the following: */ 84 | #if defined(__BYTE_ORDER__) && !defined(BYTE_ORDER) 85 | #define BYTE_ORDER __BYTE_ORDER__ 86 | #endif 87 | #if defined(__ORDER_LITTLE_ENDIAN__) && !defined(LITTLE_ENDIAN) 88 | #define LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__ 89 | #endif 90 | #if defined(__ORDER_BIG_ENDIAN__) && !defined(BIG_ENDIAN) 91 | #define BIG_ENDIAN __ORDER_BIG_ENDIAN__ 92 | #endif 93 | 94 | #if !defined(PDP_ENDIAN) 95 | #if defined(__ORDER_PDP_ENDIAN__) 96 | #define PDP_ENDIAN __ORDER_PDP_ENDIAN__ 97 | #elif defined(__PDP_ENDIAN) 98 | #define PDP_ENDIAN __PDP_ENDIAN 99 | #else 100 | #define PDP_ENDIAN 3412 101 | #endif 102 | #endif /* NUXI endian -- unsupported */ 103 | 104 | #if defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) 105 | 106 | # if (BYTE_ORDER != LITTLE_ENDIAN) && (BYTE_ORDER != BIG_ENDIAN) 107 | # error "Unsupported endianness." 108 | # endif 109 | 110 | #else /* one of the definitions is mising. */ 111 | 112 | # undef BYTE_ORDER 113 | # undef LITTLE_ENDIAN 114 | # undef BIG_ENDIAN 115 | # define LITTLE_ENDIAN 1234 116 | # define BIG_ENDIAN 4321 117 | 118 | #endif /* byte order defs */ 119 | 120 | 121 | #if !defined(BYTE_ORDER) /* good assumptions: */ 122 | 123 | /* try the compiler-predefined endianness macros. 124 | * Ref.: https://sf.net/p/predef/wiki/Endianness/ 125 | */ 126 | # if defined(__BIG_ENDIAN__) || defined(_BIG_ENDIAN) 127 | # define BYTE_ORDER BIG_ENDIAN 128 | 129 | # elif defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \ 130 | defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) 131 | # define BYTE_ORDER BIG_ENDIAN 132 | 133 | # elif defined(__LITTLE_ENDIAN__) || defined(_LITTLE_ENDIAN) 134 | # define BYTE_ORDER LITTLE_ENDIAN 135 | 136 | # elif defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \ 137 | defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) 138 | # define BYTE_ORDER LITTLE_ENDIAN 139 | 140 | /* assumptions based on OS and/or architecture macros. Some refs: 141 | * predef/other/endian.h from the boost library 142 | * http://labs.hoffmanlabs.com/node/544 143 | * https://blogs.msdn.com/larryosterman/archive/2005/06/07/426334.aspx 144 | */ 145 | # elif defined(__i386) || defined(__i386__) || defined(__386__) || defined(_M_IX86) || defined(__I386__) 146 | # define BYTE_ORDER LITTLE_ENDIAN /* any x86 */ 147 | 148 | # elif defined(__amd64) || defined(__x86_64__) || defined(_M_X64) 149 | # define BYTE_ORDER LITTLE_ENDIAN /* any x64 */ 150 | 151 | # elif defined(__mc68000__) || defined(__M68K__) || defined(__m68k__) || defined(__MC68K__) 152 | # define BYTE_ORDER BIG_ENDIAN /* Motorola 68k */ 153 | 154 | # elif defined(__sun) || defined(__svr4__) /* solaris */ 155 | # if defined(_LITTLE_ENDIAN) /* x86 */ 156 | # define BYTE_ORDER LITTLE_ENDIAN 157 | # elif defined(_BIG_ENDIAN) /* sparc */ 158 | # define BYTE_ORDER BIG_ENDIAN 159 | # endif 160 | 161 | # elif defined(__hppa) || defined(__hppa__) 162 | # define BYTE_ORDER BIG_ENDIAN /* PARISC */ 163 | 164 | # elif defined(__sparc) || defined(__sparc__) 165 | # define BYTE_ORDER BIG_ENDIAN /* SPARC -- cf. boost/predef/other/endian.h */ 166 | 167 | # elif defined(__DJGPP__) || defined(__MSDOS__) || defined(__DOS__) || defined(_DOS) 168 | # define BYTE_ORDER LITTLE_ENDIAN /* DOS */ 169 | 170 | # elif defined(__OS2__) || defined(__EMX__) 171 | # define BYTE_ORDER LITTLE_ENDIAN /* OS2 */ 172 | 173 | # elif defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) || defined(__NT__) || defined(_Windows) 174 | # define BYTE_ORDER LITTLE_ENDIAN /* Windows */ 175 | 176 | # endif 177 | 178 | #endif /* good assumptions */ 179 | 180 | 181 | #if !defined(BYTE_ORDER) /* [un]safe assumptions: */ 182 | 183 | /* assumptions based on OS and/or architecture macros. 184 | * proceed carefully: many of these are bi-endian CPUs. 185 | */ 186 | # if defined(__ppc__) || defined(__powerpc__) || defined(__POWERPC__) || defined(__PPC__) 187 | # define BYTE_ORDER BIG_ENDIAN 188 | 189 | # elif defined(__alpha__) || defined(__alpha) 190 | # define BYTE_ORDER LITTLE_ENDIAN 191 | 192 | # elif defined(__mips__) || defined(__MIPS__) 193 | # define BYTE_ORDER BIG_ENDIAN 194 | 195 | # endif 196 | 197 | # if defined(BYTE_ORDER) && 0 /* change to 1 to for warnings */ 198 | # if (BYTE_ORDER == LITTLE_ENDIAN) 199 | # warning "Using LIL endian as a SAFE default." 200 | # else /*(BYTE_ORDER == BIG_ENDIAN)*/ 201 | # warning "Using BIG endian as a SAFE default." 202 | # endif 203 | # endif 204 | 205 | #endif /* [un]safe assumptions */ 206 | 207 | 208 | #if !defined(BYTE_ORDER) 209 | # error Could not determine BYTE_ORDER 210 | #endif 211 | 212 | /* for autotools compatibility */ 213 | #if (BYTE_ORDER == BIG_ENDIAN) && !defined(WORDS_BIGENDIAN) 214 | # define WORDS_BIGENDIAN 1 215 | #endif 216 | #if (BYTE_ORDER != BIG_ENDIAN) && defined(WORDS_BIGENDIAN) 217 | #error WORDS_BIGENDIAN defined for non-BIG_ENDIAN 218 | #endif 219 | 220 | #endif /* TIMI_ENDIAN_H */ 221 | -------------------------------------------------------------------------------- /src/timidity.h: -------------------------------------------------------------------------------- 1 | /* libTiMidity -- MIDI to WAVE converter library 2 | * libTiMidity is licensed under the terms of the GNU Lesser General 3 | * Public License: see COPYING for details. 4 | * Copyright (C) 1995 Tuukka Toivonen 5 | * Copyright (C) 2004 Konstantin Korikov 6 | * Copyright (C) 2014 O.Sezer 7 | * 8 | * Note that the included TiMidity source, based on timidity-0.2i, was 9 | * originally licensed under the GPL, but the author extended it so it 10 | * can also be used separately under the GNU LGPL or the Perl Artistic 11 | * License: see the notice by Tuukka Toivonen as it appears on the web 12 | * at http://ieee.uwaterloo.ca/sca/www.cgs.fi/tt/timidity/ . 13 | */ 14 | 15 | /* 16 | * TiMidity -- Experimental MIDI to WAVE converter 17 | * Copyright (C) 1995 Tuukka Toivonen 18 | * 19 | * This program is free software; you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation; either version 2 of the License, or (at 22 | * your option) any later version. 23 | * 24 | * This program is distributed in the hope that it will be useful, but 25 | * WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 27 | * 28 | * See the GNU General Public License for more details. 29 | * 30 | * You should have received a copy of the GNU General Public License along 31 | * with this program; if not, write to the Free Software Foundation, Inc., 32 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 33 | */ 34 | 35 | #ifndef LIBTIMIDITY_H 36 | #define LIBTIMIDITY_H 37 | 38 | #include 39 | #include 40 | 41 | #ifdef __cplusplus 42 | extern "C" { 43 | #endif 44 | 45 | #define LIBTIMIDITY_VERSION_MAJOR 0L 46 | #define LIBTIMIDITY_VERSION_MINOR 2L 47 | #define LIBTIMIDITY_PATCHLEVEL 7L 48 | 49 | #define LIBTIMIDITY_VERSION \ 50 | ((LIBTIMIDITY_VERSION_MAJOR<<16)| \ 51 | (LIBTIMIDITY_VERSION_MINOR<< 8)| \ 52 | (LIBTIMIDITY_PATCHLEVEL)) 53 | 54 | /* Audio format flags (defaults to LSB byte order) 55 | */ 56 | #define MID_AUDIO_U8 0x0008 /* Unsigned 8-bit samples */ 57 | #define MID_AUDIO_S8 0x8008 /* Signed 8-bit samples */ 58 | #define MID_AUDIO_U16LSB 0x0010 /* Unsigned 16-bit samples */ 59 | #define MID_AUDIO_S16LSB 0x8010 /* Signed 16-bit samples */ 60 | #define MID_AUDIO_U16MSB 0x1010 /* As above, but big-endian byte order */ 61 | #define MID_AUDIO_S16MSB 0x9010 /* As above, but big-endian byte order */ 62 | #define MID_AUDIO_U16 MID_AUDIO_U16LSB 63 | #define MID_AUDIO_S16 MID_AUDIO_S16LSB 64 | 65 | /* Core Library Types 66 | */ 67 | #ifndef __amigaos4__ 68 | typedef unsigned char uint8; 69 | typedef signed char sint8; 70 | typedef unsigned short uint16; 71 | typedef signed short sint16; 72 | typedef unsigned int uint32; 73 | typedef signed int sint32; 74 | #else 75 | #include 76 | typedef int8 sint8; 77 | typedef int16 sint16; 78 | typedef int32 sint32; 79 | #endif 80 | 81 | typedef size_t (*MidIStreamReadFunc) (void *ctx, void *ptr, size_t size, size_t nmemb); 82 | typedef int (*MidIStreamSeekFunc) (void *ctx, long offset, int whence); 83 | typedef long (*MidIStreamTellFunc) (void *ctx); 84 | typedef int (*MidIStreamCloseFunc)(void *ctx); 85 | 86 | typedef struct _MidIStream MidIStream; 87 | typedef struct _MidDLSPatches MidDLSPatches; 88 | typedef struct _MidSong MidSong; 89 | 90 | typedef struct _MidSongOptions MidSongOptions; 91 | struct _MidSongOptions 92 | { 93 | sint32 rate; /* DSP frequency -- samples per second */ 94 | uint16 format; /* Audio data format */ 95 | uint8 channels; /* Number of channels: 1 mono, 2 stereo */ 96 | uint8 _pad; 97 | uint16 buffer_size; /* Sample buffer size (in samples, not bytes) */ 98 | uint16 _reserved; 99 | }; 100 | 101 | typedef int MidSongMetaId; 102 | #define MID_SONG_TEXT 0 103 | #define MID_SONG_COPYRIGHT 1 104 | #define MID_META_MAX 8 105 | 106 | 107 | /* Compiler magic for shared libraries 108 | * =================================== 109 | */ 110 | #if defined(_WIN32) || defined(__CYGWIN__) 111 | /* if you are compiling for Windows and will link to the 112 | * static library, you must define TIMIDITY_STATIC in 113 | * your project. otherwise, dllimport will be assumed. */ 114 | # if defined(TIMIDITY_BUILD) && defined(DLL_EXPORT) /* building libtimidity as a dll for windows */ 115 | # define TIMI_EXPORT __declspec(dllexport) 116 | # elif defined(TIMIDITY_BUILD) || defined(TIMIDITY_STATIC) /* building or using static libtimidity for windows */ 117 | # define TIMI_EXPORT 118 | # else 119 | # define TIMI_EXPORT __declspec(dllimport) /* using libtimidity dll for windows */ 120 | # endif 121 | #elif defined(__OS2__) && defined(__WATCOMC__) 122 | # if defined(TIMIDITY_BUILD) && defined(__SW_BD) /* building libtimidity as a dll for os/2 */ 123 | # define TIMI_EXPORT __declspec(dllexport) 124 | # else 125 | # define TIMI_EXPORT /* using dll or static libtimidity for os/2 */ 126 | # endif 127 | /* SYM_VISIBILITY should be defined if both the compiler 128 | * and the target support the visibility attributes. the 129 | * configury does that automatically. for any standalone 130 | * makefiles, etc, the developer should add the required 131 | * flags, i.e.: -DSYM_VISIBILITY -fvisibility=hidden */ 132 | #elif defined(TIMIDITY_BUILD) && defined(SYM_VISIBILITY) 133 | # define TIMI_EXPORT __attribute__((visibility("default"))) 134 | #else 135 | # define TIMI_EXPORT 136 | #endif 137 | 138 | /* Core Library Functions 139 | * ====================== 140 | */ 141 | 142 | /* Retrieve library version 143 | */ 144 | TIMI_EXPORT extern long mid_get_version (void); 145 | 146 | /* Initialize the library. If config_file is NULL 147 | * search for configuratin file in default directories 148 | */ 149 | TIMI_EXPORT extern int mid_init (const char *config_file); 150 | 151 | /* Initialize the library without reading any 152 | * configuratin file 153 | */ 154 | TIMI_EXPORT extern int mid_init_no_config (void); 155 | 156 | /* Shutdown the library 157 | */ 158 | TIMI_EXPORT extern void mid_exit (void); 159 | 160 | 161 | /* Input Stream Functions 162 | * ====================== 163 | */ 164 | 165 | /* Create input stream from a file name 166 | */ 167 | TIMI_EXPORT extern MidIStream *mid_istream_open_file (const char *file); 168 | 169 | /* Create input stream from a file pointer 170 | */ 171 | TIMI_EXPORT extern MidIStream *mid_istream_open_fp (FILE *fp, int autoclose); 172 | 173 | /* Create input stream from memory 174 | */ 175 | TIMI_EXPORT extern MidIStream *mid_istream_open_mem (void *mem, size_t size); 176 | 177 | /* Create custom input stream 178 | */ 179 | TIMI_EXPORT extern MidIStream *mid_istream_open_callbacks (MidIStreamReadFunc readfn, 180 | MidIStreamSeekFunc seekfn, 181 | MidIStreamTellFunc tellfn, 182 | MidIStreamCloseFunc closefn, 183 | void *context); 184 | 185 | /* Read data from input stream 186 | */ 187 | TIMI_EXPORT extern size_t mid_istream_read (MidIStream *stream, void *ptr, size_t size, 188 | size_t nmemb); 189 | 190 | /* Seek to a position in the input stream 191 | */ 192 | TIMI_EXPORT extern int mid_istream_seek (MidIStream *stream, long offset, int whence); 193 | 194 | /* Tell the position of input stream 195 | */ 196 | TIMI_EXPORT extern long mid_istream_tell (MidIStream *stream); 197 | 198 | /* Skip data from input stream 199 | */ 200 | TIMI_EXPORT extern int mid_istream_skip (MidIStream *stream, long len); 201 | 202 | /* Close and destroy input stream 203 | */ 204 | TIMI_EXPORT extern int mid_istream_close (MidIStream *stream); 205 | 206 | 207 | /* DLS Patch Functions 208 | * =================== 209 | */ 210 | 211 | /* Load DLS patches - No longer supported: Always returns NULL. 212 | */ 213 | TIMI_EXPORT extern MidDLSPatches *mid_dlspatches_load (MidIStream *stream); 214 | 215 | /* Destroy DLS patches 216 | */ 217 | TIMI_EXPORT extern void mid_dlspatches_free (MidDLSPatches *data); 218 | 219 | 220 | /* MIDI Song Functions 221 | * =================== 222 | */ 223 | 224 | /* Load MIDI song 225 | */ 226 | TIMI_EXPORT extern MidSong *mid_song_load (MidIStream *stream, 227 | MidSongOptions *options); 228 | 229 | /* Load MIDI song with specified DLS patches 230 | * No longer supported: Always returns NULL. 231 | */ 232 | TIMI_EXPORT extern MidSong *mid_song_load_dls (MidIStream *stream, 233 | MidDLSPatches *dlspatches, 234 | MidSongOptions *options); 235 | 236 | /* Set song amplification value 237 | */ 238 | TIMI_EXPORT extern void mid_song_set_volume (MidSong *song, int volume); 239 | 240 | /* Seek song to the start position and initialize conversion 241 | */ 242 | TIMI_EXPORT extern void mid_song_start (MidSong *song); 243 | 244 | /* Read WAVE data 245 | */ 246 | TIMI_EXPORT extern size_t mid_song_read_wave (MidSong *song, sint8 *ptr, size_t size); 247 | 248 | /* Seek song to specified offset in milliseconds 249 | */ 250 | TIMI_EXPORT extern void mid_song_seek (MidSong *song, uint32 ms); 251 | 252 | /* Get total song time in milliseconds 253 | */ 254 | TIMI_EXPORT extern uint32 mid_song_get_total_time (MidSong *song); 255 | 256 | /* Get current song time in milliseconds 257 | */ 258 | TIMI_EXPORT extern uint32 mid_song_get_time (MidSong *song); 259 | 260 | /* Get song meta data. Return NULL if no meta data. 261 | */ 262 | TIMI_EXPORT extern char *mid_song_get_meta (MidSong *song, MidSongMetaId what); 263 | 264 | /* Destroy song 265 | */ 266 | TIMI_EXPORT extern void mid_song_free (MidSong *song); 267 | 268 | #ifdef __cplusplus 269 | } 270 | #endif 271 | 272 | #endif /* LIBTIMIDITY_H */ 273 | -------------------------------------------------------------------------------- /src/timidity_internal.h: -------------------------------------------------------------------------------- 1 | /* libTiMidity -- MIDI to WAVE converter library 2 | * libTiMidity is licensed under the terms of the GNU Lesser General 3 | * Public License: see COPYING for details. 4 | * Copyright (C) 1995 Tuukka Toivonen 5 | * Copyright (C) 2004 Konstantin Korikov 6 | * 7 | * Note that the included TiMidity source, based on timidity-0.2i, was 8 | * originally licensed under the GPL, but the author extended it so it 9 | * can also be used separately under the GNU LGPL or the Perl Artistic 10 | * License: see the notice by Tuukka Toivonen as it appears on the web 11 | * at http://ieee.uwaterloo.ca/sca/www.cgs.fi/tt/timidity/ . 12 | */ 13 | 14 | /* 15 | * TiMidity -- Experimental MIDI to WAVE converter 16 | * Copyright (C) 1995 Tuukka Toivonen 17 | * 18 | * This program is free software; you can redistribute it and/or modify 19 | * it under the terms of the GNU General Public License as published by 20 | * the Free Software Foundation; either version 2 of the License, or (at 21 | * your option) any later version. 22 | * 23 | * This program is distributed in the hope that it will be useful, but 24 | * WITHOUT ANY WARRANTY; without even the implied warranty of 25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 26 | * 27 | * See the GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License along 30 | * with this program; if not, write to the Free Software Foundation, Inc., 31 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 32 | */ 33 | 34 | #ifndef TIMIDITY_INTERNAL_H 35 | #define TIMIDITY_INTERNAL_H 36 | 37 | /* hide private symbols by prefixing with "_timi_" */ 38 | #undef TIMI_NAMESPACE 39 | #define TIMI_NAMESPACE(x) _timi_ ## x 40 | 41 | #if defined(__OS2__) || defined(__EMX__) 42 | #include 43 | #endif 44 | #include "timidity.h" 45 | #include "options.h" 46 | 47 | #if defined(_MSC_VER) && !defined(__cplusplus) && !defined(HAVE_CONFIG_H) 48 | #define inline __inline 49 | #endif 50 | #ifndef HAVE_CONFIG_H 51 | #include "timi_endian.h" 52 | #endif 53 | 54 | /* Instrument files are little-endian, MIDI files big-endian, so we 55 | need to do some conversions. */ 56 | #if defined(__VBCC__) && defined(__M68K__) 57 | uint16 XCHG_SHORT(__reg("d0") uint16) = 58 | "\trol.w\t#8,d0"; 59 | sint32 XCHG_LONG (__reg("d0") sint32) = 60 | "\trol.w\t#8,d0\n" 61 | "\tswap\td0\n" 62 | "\trol.w\t#8,d0"; 63 | 64 | #elif defined(__WATCOMC__) && defined(__386__) 65 | extern uint16 XCHG_SHORT(uint16); 66 | extern sint32 XCHG_LONG (sint32); 67 | #ifndef __SW_3 /* 486+ */ 68 | #pragma aux XCHG_LONG = \ 69 | "bswap eax" \ 70 | parm [eax] \ 71 | modify [eax]; 72 | #else /* 386-only */ 73 | #pragma aux XCHG_LONG = \ 74 | "xchg al, ah" \ 75 | "ror eax, 16" \ 76 | "xchg al, ah" \ 77 | parm [eax] \ 78 | modify [eax]; 79 | #endif 80 | #pragma aux XCHG_SHORT = \ 81 | "xchg al, ah" \ 82 | parm [ax] \ 83 | modify [ax]; 84 | 85 | #else 86 | #define XCHG_SHORT(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF)) 87 | #ifdef __i486__ 88 | # define XCHG_LONG(x) \ 89 | ({ sint32 __value; \ 90 | asm ("bswap %1; movl %1,%0" : "=g" (__value) : "r" (x)); \ 91 | __value; }) 92 | #else 93 | # define XCHG_LONG(x) ((((x)&0xFF)<<24) | \ 94 | (((x)&0xFF00)<<8) | \ 95 | (((x)&0xFF0000)>>8) | \ 96 | (((x)>>24)&0xFF)) 97 | #endif 98 | #endif 99 | 100 | #if !defined(WORDS_BIGENDIAN) 101 | #define SWAPLE16(x) x 102 | #define SWAPLE32(x) x 103 | #define SWAPBE16(x) XCHG_SHORT(x) 104 | #define SWAPBE32(x) XCHG_LONG(x) 105 | #else 106 | #define SWAPBE16(x) x 107 | #define SWAPBE32(x) x 108 | #define SWAPLE16(x) XCHG_SHORT(x) 109 | #define SWAPLE32(x) XCHG_LONG(x) 110 | #endif 111 | 112 | #if defined(__GNUC__) && !(defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) 113 | /* this is more compatible with very old gcc */ 114 | #ifdef TIMIDITY_DEBUG 115 | #define DEBUG_MSG(fmt, args...) fprintf(stderr, fmt, ##args) 116 | #else 117 | #define DEBUG_MSG(fmt, args...) 118 | #endif 119 | #else /* use C99 varargs macros */ 120 | #ifdef TIMIDITY_DEBUG 121 | #define DEBUG_MSG(...) fprintf(stderr, __VA_ARGS__) 122 | #else 123 | #define DEBUG_MSG(...) 124 | #endif 125 | #endif 126 | 127 | #ifndef __VBCC__ 128 | #define TIMI_UNUSED(x) (void)(x) 129 | #else 130 | #define TIMI_UNUSED(x) /* vbcc emits an annoying warning for (void)(x) */ 131 | #endif 132 | 133 | 134 | #define MID_VIBRATO_SAMPLE_INCREMENTS 32 135 | 136 | /* Maximum polyphony. */ 137 | #define MID_MAX_VOICES 48 138 | 139 | typedef sint16 sample_t; 140 | typedef sint32 final_volume_t; 141 | 142 | typedef struct _MidSample MidSample; 143 | struct _MidSample 144 | { 145 | sint32 146 | loop_start, loop_end, data_length, 147 | sample_rate, 148 | low_freq, high_freq, root_freq; 149 | sint32 envelope_rate[6], envelope_offset[6]; 150 | float volume; 151 | sample_t *data; 152 | sint32 153 | tremolo_sweep_increment, tremolo_phase_increment, 154 | vibrato_sweep_increment, vibrato_control_ratio; 155 | uint8 tremolo_depth, vibrato_depth, modes; 156 | sint8 panning, note_to_use; 157 | }; 158 | 159 | typedef struct _MidChannel MidChannel; 160 | struct _MidChannel 161 | { 162 | int bank, program, volume, sustain, panning, pitchbend, expression; 163 | int mono; /* one note only on this channel -- not implemented yet */ 164 | int pitchsens; 165 | /* chorus, reverb... Coming soon to a 300-MHz, eight-way superscalar 166 | processor near you */ 167 | float pitchfactor; /* precomputed pitch bend factor to save some fdiv's */ 168 | }; 169 | 170 | typedef struct _MidVoice MidVoice; 171 | struct _MidVoice 172 | { 173 | uint8 status, channel, note, velocity; 174 | MidSample *sample; 175 | sint32 176 | orig_frequency, frequency, 177 | sample_offset, sample_increment, 178 | envelope_volume, envelope_target, envelope_increment, 179 | tremolo_sweep, tremolo_sweep_position, 180 | tremolo_phase, tremolo_phase_increment, 181 | vibrato_sweep, vibrato_sweep_position; 182 | 183 | final_volume_t left_mix, right_mix; 184 | 185 | float left_amp, right_amp, tremolo_volume; 186 | sint32 vibrato_sample_increment[MID_VIBRATO_SAMPLE_INCREMENTS]; 187 | int 188 | vibrato_phase, vibrato_control_ratio, vibrato_control_counter, 189 | envelope_stage, control_counter, panning, panned; 190 | }; 191 | 192 | typedef struct _MidInstrument MidInstrument; 193 | struct _MidInstrument 194 | { 195 | int samples; 196 | MidSample *sample; 197 | }; 198 | 199 | typedef struct _MidToneBankElement MidToneBankElement; 200 | struct _MidToneBankElement 201 | { 202 | char *name; 203 | int note, amp, pan, strip_loop, strip_envelope, strip_tail; 204 | }; 205 | 206 | typedef struct _MidToneBank MidToneBank; 207 | struct _MidToneBank 208 | { 209 | MidToneBankElement *tone; 210 | MidInstrument *instrument[128]; 211 | }; 212 | 213 | typedef struct _MidEvent MidEvent; 214 | struct _MidEvent 215 | { 216 | sint32 time; 217 | uint8 channel, type, a, b; 218 | }; 219 | 220 | typedef struct _MidEventList MidEventList; 221 | struct _MidEventList 222 | { 223 | MidEvent event; 224 | struct _MidEventList *next; 225 | }; 226 | 227 | struct _MidSong 228 | { 229 | int oom; /* malloc() failed */ 230 | int playing; 231 | sint32 rate; 232 | sint32 encoding; 233 | int bytes_per_sample; 234 | float master_volume; 235 | sint32 amplification; 236 | MidToneBank *tonebank[128]; 237 | MidToneBank *drumset[128]; 238 | MidInstrument *default_instrument; 239 | int default_program; 240 | void (*write) (void *dp, sint32 *lp, sint32 c); 241 | int buffer_size; 242 | sample_t *resample_buffer; 243 | sint32 *common_buffer; 244 | /* These would both fit into 32 bits, but they are often added in 245 | large multiples, so it's simpler to have two roomy ints */ 246 | /* samples per MIDI delta-t */ 247 | sint32 sample_increment; 248 | sint32 sample_correction; 249 | MidChannel channel[16]; 250 | MidVoice voice[MID_MAX_VOICES]; 251 | int voices; 252 | sint32 drumchannels; 253 | sint32 control_ratio; 254 | sint32 lost_notes; 255 | sint32 cut_notes; 256 | sint32 samples; 257 | MidEvent *events; 258 | MidEvent *current_event; 259 | MidEventList *evlist; 260 | sint32 current_sample; 261 | sint32 event_count; 262 | sint32 at; 263 | sint32 groomed_event_count; 264 | char *meta_data[MID_META_MAX]; 265 | }; 266 | 267 | #endif /* TIMIDITY_INTERNAL_H */ 268 | -------------------------------------------------------------------------------- /tests/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | if HAVE_AO 3 | PLAYMIDI = playmidi 4 | else 5 | PLAYMIDI = 6 | endif 7 | 8 | noinst_PROGRAMS = midi2raw $(PLAYMIDI) 9 | 10 | AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/src 11 | LDADD = $(top_builddir)/src/libtimidity.la @LIBTIMIDITY_LIBS@ 12 | 13 | midi2raw_SOURCES = midi2raw.c 14 | 15 | playmidi_SOURCES = playmidi.c 16 | playmidi_LDADD = $(LDADD) @AO_LIBS@ 17 | playmidi_CFLAGS = @AO_CFLAGS@ 18 | 19 | noinst_SCRIPTS = runtest.sh 20 | TESTS = runtest.sh 21 | 22 | EXTRA_DIST = ame002.mid runtest.sh 23 | -------------------------------------------------------------------------------- /tests/ame002.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sezero/libtimidity/61bfd3ad9c42561ffe4552b426c0c79514754525/tests/ame002.mid -------------------------------------------------------------------------------- /tests/midi2raw.c: -------------------------------------------------------------------------------- 1 | /* midi2raw.c -- MIDI to RAW WAVE data converter using libtimidity 2 | * Copyright (C) 2004 Konstantin Korikov 3 | * This example is distributed in the hope that it will be useful, 4 | * but WITHOUT ANY WARRENTY; without event the implied warrenty of 5 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include "timidity.h" 12 | 13 | void 14 | print_usage(void) 15 | { 16 | printf("Usage: midi2raw [-cfg /path/to/your/timidity.cfg]\n" 17 | " [-r rate] [-s sample_width] [-c channels]\n" 18 | " [-v volume] [-o output_file] [midifile]\n"); 19 | } 20 | 21 | int 22 | main (int argc, char *argv[]) 23 | { 24 | int rate = 44100; 25 | int bits = 16; 26 | int channels = 2; 27 | int volume = 100; 28 | FILE * output = stdout; 29 | const char *outname = NULL; 30 | char * cfgfile = NULL; 31 | int arg; 32 | MidIStream *stream; 33 | MidSongOptions options; 34 | MidSong *song; 35 | sint8 buffer[4096]; 36 | size_t bytes_read; 37 | 38 | for (arg = 1; arg < argc; arg++) 39 | { 40 | if (!strcmp(argv[arg], "-r")) 41 | { 42 | if (++arg >= argc) break; 43 | rate = atoi (argv[arg]); 44 | if (rate < 4000 || rate > 256000) 45 | { 46 | fprintf (stderr, "Invalid rate\n"); 47 | return 1; 48 | } 49 | } 50 | else if (!strcmp(argv[arg], "-s")) 51 | { 52 | if (++arg >= argc) break; 53 | bits = atoi (argv[arg]); 54 | if (bits != 8 && bits != 16) 55 | { 56 | fprintf (stderr, "Invalid sample width\n"); 57 | return 1; 58 | } 59 | } 60 | else if (!strcmp(argv[arg], "-c")) 61 | { 62 | if (++arg >= argc) break; 63 | channels = atoi (argv[arg]); 64 | if (channels < 1 || channels > 2) 65 | { 66 | fprintf (stderr, "Invalid number of channels\n"); 67 | return 1; 68 | } 69 | } 70 | else if (!strcmp(argv[arg], "-v")) 71 | { 72 | if (++arg >= argc) break; 73 | volume = atoi (argv[arg]); 74 | if (volume < 0) 75 | { 76 | fprintf (stderr, "Invalid volume\n"); 77 | return 1; 78 | } 79 | } 80 | else if (!strcmp(argv[arg], "-o")) 81 | { 82 | if (++arg >= argc) break; 83 | outname = argv[arg]; 84 | } 85 | else if (!strcmp(argv[arg], "-cfg")) 86 | { 87 | if (++arg >= argc) break; 88 | cfgfile = (char *) malloc (strlen(argv[arg]) + 1); 89 | if (cfgfile == NULL) 90 | { 91 | fprintf (stderr, "Failed allocating memory.\n"); 92 | return 1; 93 | } 94 | strcpy(cfgfile,argv[arg]); 95 | } 96 | else if (!strcmp(argv[arg], "-h")) 97 | { 98 | print_usage(); 99 | return 0; 100 | } 101 | else if (argv[arg][0] == '-') 102 | { 103 | fprintf (stderr, "Unknown option: %s\n", argv[arg]); 104 | print_usage(); 105 | return 1; 106 | } 107 | else break; 108 | } 109 | 110 | if (mid_init (cfgfile) < 0) 111 | { 112 | fprintf (stderr, "Could not initialise libTiMidity\n"); 113 | free (cfgfile); 114 | return 1; 115 | } 116 | 117 | if (arg >= argc) 118 | { 119 | stream = mid_istream_open_fp (stdin, 0); 120 | } 121 | else 122 | { 123 | stream = mid_istream_open_file (argv[arg]); 124 | if (stream == NULL) 125 | { 126 | fprintf (stderr, "Could not open file %s\n", argv[arg]); 127 | mid_exit (); 128 | free (cfgfile); 129 | return 1; 130 | } 131 | } 132 | 133 | options.rate = rate; 134 | options.format = (bits == 16)? MID_AUDIO_S16LSB : MID_AUDIO_U8; 135 | options.channels = channels; 136 | options.buffer_size = sizeof (buffer) / (bits * channels / 8); 137 | 138 | song = mid_song_load (stream, &options); 139 | mid_istream_close (stream); 140 | 141 | if (song == NULL) 142 | { 143 | fprintf (stderr, "Invalid MIDI file\n"); 144 | mid_exit (); 145 | free (cfgfile); 146 | return 1; 147 | } 148 | 149 | if (outname && !(output = fopen (outname, "wb"))) 150 | { 151 | fprintf (stderr, "Could not open output file %s\n", outname); 152 | mid_song_free (song); 153 | mid_exit (); 154 | free (cfgfile); 155 | return 1; 156 | } 157 | 158 | mid_song_set_volume (song, volume); 159 | mid_song_start (song); 160 | 161 | while ((bytes_read = mid_song_read_wave (song, buffer, sizeof (buffer)))) 162 | fwrite (buffer, bytes_read, 1, output); 163 | 164 | mid_song_free (song); 165 | mid_exit (); 166 | free (cfgfile); 167 | if (outname) fclose(output); 168 | 169 | return 0; 170 | } 171 | -------------------------------------------------------------------------------- /tests/playmidi.c: -------------------------------------------------------------------------------- 1 | /* playmidi.c -- play MIDI files using libtimidity and libao 2 | * Copyright (C) 2004 Konstantin Korikov 3 | * This example is distributed in the hope that it will be useful, 4 | * but WITHOUT ANY WARRENTY; without event the implied warrenty of 5 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "timidity.h" 13 | 14 | void 15 | print_usage(void) 16 | { 17 | printf("Usage: playmidi [-cfg /path/to/your/timidity.cfg]\n" 18 | " [-r rate] [-s sample_width] [-c channels]\n" 19 | " [-v volume] [-q] [midifile]\n"); 20 | } 21 | 22 | int 23 | main (int argc, char *argv[]) 24 | { 25 | int rate = 44100; 26 | int bits = 16; 27 | int channels = 2; 28 | int volume = 100; 29 | int quiet = 0; 30 | char * cfgfile = NULL; 31 | int arg; 32 | MidIStream *stream; 33 | MidSongOptions options; 34 | MidSong *song; 35 | long total_time; 36 | sint8 *buffer; 37 | size_t buffer_size; 38 | ao_device *device; 39 | ao_sample_format format; 40 | int default_driver; 41 | size_t bytes_read; 42 | 43 | for (arg = 1; arg < argc; arg++) 44 | { 45 | if (!strcmp(argv[arg], "-r")) 46 | { 47 | if (++arg >= argc) break; 48 | rate = atoi (argv[arg]); 49 | if (rate < 4000 || rate > 256000) 50 | { 51 | fprintf (stderr, "Invalid rate\n"); 52 | return 1; 53 | } 54 | } 55 | else if (!strcmp(argv[arg], "-s")) 56 | { 57 | if (++arg >= argc) break; 58 | bits = atoi (argv[arg]); 59 | if (bits != 8 && bits != 16) 60 | { 61 | fprintf (stderr, "Invalid sample width\n"); 62 | return 1; 63 | } 64 | } 65 | else if (!strcmp(argv[arg], "-c")) 66 | { 67 | if (++arg >= argc) break; 68 | channels = atoi (argv[arg]); 69 | if (channels < 1 || channels > 2) 70 | { 71 | fprintf (stderr, "Invalid number of channels\n"); 72 | return 1; 73 | } 74 | } 75 | else if (!strcmp(argv[arg], "-v")) 76 | { 77 | if (++arg >= argc) break; 78 | volume = atoi (argv[arg]); 79 | if (volume < 0) 80 | { 81 | fprintf (stderr, "Invalid volume\n"); 82 | return 1; 83 | } 84 | } 85 | else if (!strcmp(argv[arg], "-q")) 86 | { 87 | quiet = 1; 88 | } 89 | else if (!strcmp(argv[arg], "-cfg")) 90 | { 91 | if (++arg >= argc) break; 92 | cfgfile = (char *) malloc (strlen(argv[arg]) + 1); 93 | if (cfgfile == NULL) 94 | { 95 | fprintf (stderr, "Failed allocating memory.\n"); 96 | return 1; 97 | } 98 | strcpy(cfgfile,argv[arg]); 99 | } 100 | else if (!strcmp(argv[arg], "-h")) 101 | { 102 | print_usage(); 103 | return 0; 104 | } 105 | else if (argv[arg][0] == '-') 106 | { 107 | fprintf (stderr, "Unknown option: %s\n", argv[arg]); 108 | print_usage(); 109 | return 1; 110 | } 111 | else break; 112 | } 113 | 114 | if (mid_init (cfgfile) < 0) 115 | { 116 | fprintf (stderr, "Could not initialise libTiMidity\n"); 117 | free (cfgfile); 118 | return 1; 119 | } 120 | 121 | if (arg >= argc) 122 | { 123 | stream = mid_istream_open_fp (stdin, 0); 124 | } 125 | else 126 | { 127 | stream = mid_istream_open_file (argv[arg]); 128 | if (stream == NULL) 129 | { 130 | fprintf (stderr, "Could not open file %s\n", argv[arg]); 131 | mid_exit (); 132 | free (cfgfile); 133 | return 1; 134 | } 135 | } 136 | 137 | options.rate = rate; 138 | options.format = (bits == 16)? MID_AUDIO_S16LSB : MID_AUDIO_U8; 139 | options.channels = channels; 140 | options.buffer_size = rate; 141 | 142 | song = mid_song_load (stream, &options); 143 | mid_istream_close (stream); 144 | 145 | if (song == NULL) 146 | { 147 | fprintf (stderr, "Invalid MIDI file\n"); 148 | mid_exit (); 149 | free (cfgfile); 150 | return 1; 151 | } 152 | 153 | total_time = mid_song_get_total_time (song); 154 | 155 | mid_song_set_volume (song, volume); 156 | mid_song_start (song); 157 | 158 | ao_initialize (); 159 | default_driver = ao_default_driver_id (); 160 | memset(&format, 0, sizeof(format)); 161 | format.bits = bits; 162 | format.channels = channels; 163 | format.rate = rate; 164 | format.byte_format = AO_FMT_LITTLE; 165 | 166 | device = ao_open_live (default_driver, &format, NULL); 167 | if (device == NULL) 168 | { 169 | fprintf (stderr, "Error opening device.\n"); 170 | ao_shutdown (); 171 | mid_song_free (song); 172 | mid_exit (); 173 | free (cfgfile); 174 | return 1; 175 | } 176 | 177 | if (!quiet) 178 | { 179 | const char *title = mid_song_get_meta (song, MID_SONG_TEXT); 180 | long ver = mid_get_version (); 181 | if (title == NULL) 182 | { 183 | if (arg < argc) title = argv[arg]; 184 | else title = "stdin"; 185 | } 186 | printf ("Playing: %s, using libTiMidity v%ld.%ld.%ld\n", 187 | title, (ver>>16) & 255, (ver>>8) & 255, ver & 255); 188 | } 189 | 190 | buffer_size = bits * channels / 8 * rate; 191 | buffer = (sint8 *) malloc (buffer_size); 192 | 193 | do 194 | { 195 | if (!quiet) 196 | { 197 | long time = mid_song_get_time (song); 198 | printf ("\rTime: %02ld:%02ld/%02ld:%02ld", 199 | time / 60000, (time / 1000) % 60, 200 | total_time / 60000, (total_time / 1000) % 60); 201 | fflush (stdout); 202 | } 203 | bytes_read = mid_song_read_wave (song, buffer, buffer_size); 204 | ao_play (device, (char *) buffer, bytes_read); 205 | } 206 | while (bytes_read); 207 | 208 | free (buffer); 209 | 210 | if (!quiet) 211 | printf ("\n"); 212 | 213 | ao_close (device); 214 | ao_shutdown (); 215 | mid_song_free (song); 216 | mid_exit (); 217 | free (cfgfile); 218 | 219 | return 0; 220 | } 221 | -------------------------------------------------------------------------------- /tests/runtest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Try to test library 4 | 5 | [ "x$builddir" = "x" ] && builddir="." 6 | [ "x$srcdir" = "x" ] && srcdir="." 7 | midi_file="$srcdir/ame002.mid" 8 | midi2raw_opts="-r 44100 -s 16 -c 2" 9 | play_cmd="" 10 | 11 | if [ -x "$builddir/playmidi" ]; then 12 | echo "Running: $builddir/playmidi $midi_file" 13 | exec "$builddir/playmidi" "$midi_file" 14 | elif [ "x`which aplay 2>/dev/null`" != "x" ]; then 15 | play_cmd="aplay -f cd -" 16 | elif [ "x`which play 2>/dev/null`" != "x" ]; then 17 | play_cmd="play -r 44100 -s -b 16 -c 2 -t raw -" 18 | else 19 | echo "No command found for sound output!\n" >&2 20 | exit 1 21 | fi 22 | 23 | if [ "x$play_cmd" != "x" ]; then 24 | echo "Running: $builddir/midi2raw $midi2raw_opts $midi_file |$play_cmd" 25 | exec "$builddir/midi2raw" $midi2raw_opts "$midi_file" |$play_cmd 26 | fi 27 | --------------------------------------------------------------------------------