diff options
Diffstat (limited to 'apps/plugins/midi2wav.c')
-rw-r--r-- | apps/plugins/midi2wav.c | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/apps/plugins/midi2wav.c b/apps/plugins/midi2wav.c new file mode 100644 index 0000000000..f8368535d1 --- /dev/null +++ b/apps/plugins/midi2wav.c | |||
@@ -0,0 +1,168 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2005 Stepan Moskovchenko | ||
10 | * | ||
11 | * All files in this archive are subject to the GNU General Public License. | ||
12 | * See the file COPYING in the source tree root for full license agreement. | ||
13 | * | ||
14 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
15 | * KIND, either express or implied. | ||
16 | * | ||
17 | ****************************************************************************/ | ||
18 | |||
19 | #define SAMPLE_RATE 48000 | ||
20 | #define MAX_VOICES 100 | ||
21 | |||
22 | /* This is for writing to the DSP directly from the Simulator | ||
23 | #include <stdio.h> | ||
24 | #include <stdlib.h> | ||
25 | #include <linux/soundcard.h> | ||
26 | #include <sys/ioctl.h> | ||
27 | */ | ||
28 | |||
29 | #include "../../plugin.h" | ||
30 | #include "midi/midiutil.c" | ||
31 | #include "midi/guspat.h" | ||
32 | #include "midi/guspat.c" | ||
33 | #include "midi/sequencer.c" | ||
34 | #include "midi/midifile.c" | ||
35 | #include "midi/synth.c" | ||
36 | |||
37 | |||
38 | |||
39 | //#include "lib/xxx2wav.h" | ||
40 | |||
41 | int fd=-1; //File descriptor, for opening /dev/dsp and writing to it | ||
42 | |||
43 | extern long tempo; //The sequencer keeps track of this | ||
44 | |||
45 | |||
46 | struct plugin_api * rb; | ||
47 | |||
48 | |||
49 | |||
50 | enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | ||
51 | { | ||
52 | TEST_PLUGIN_API(api); | ||
53 | (void)parameter; | ||
54 | rb = api; | ||
55 | rb->splash(HZ*2, true, "MIDI"); | ||
56 | midimain(); | ||
57 | rb->splash(HZ*2, true, "FINISHED PLAYING"); | ||
58 | return PLUGIN_OK; | ||
59 | } | ||
60 | |||
61 | |||
62 | int midimain() | ||
63 | { | ||
64 | rb->splash(HZ*2, true, "OPENED DSP"); | ||
65 | fd=rb->open("/dsp.raw", O_WRONLY|O_CREAT); | ||
66 | /* | ||
67 | int arg, status; | ||
68 | int bit, samp, ch; | ||
69 | |||
70 | arg = 16; // sample size | ||
71 | status = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg); | ||
72 | status = ioctl(fd, SOUND_PCM_READ_BITS, &arg); | ||
73 | bit=arg; | ||
74 | |||
75 | |||
76 | arg = 2; //Number of channels, 1=mono | ||
77 | status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &arg); | ||
78 | status = ioctl(fd, SOUND_PCM_READ_CHANNELS, &arg); | ||
79 | ch=arg; | ||
80 | |||
81 | arg = SAMPLE_RATE; //Yeah. sampling rate | ||
82 | status = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg); | ||
83 | status = ioctl(fd, SOUND_PCM_READ_RATE, &arg); | ||
84 | samp=arg; | ||
85 | */ | ||
86 | |||
87 | printf("\nHello.\n"); | ||
88 | // initSound(); //Open the computer's sound card | ||
89 | int a=0; | ||
90 | |||
91 | rb->splash(HZ*2, true, "LOADING MIDI"); | ||
92 | |||
93 | struct MIDIfile * mf = loadFile("/test.mid"); | ||
94 | |||
95 | rb->splash(HZ*2, true, "LOADED MIDI"); | ||
96 | long bpm, nsmp, l; | ||
97 | |||
98 | int bp=0; | ||
99 | |||
100 | rb->splash(HZ*2, true, "LOADING PATCHES"); | ||
101 | initSynth(mf, "/iriver2.cfg", "/drums.cfg"); //Initialize the MIDI syntehsizer | ||
102 | rb->splash(HZ*2, true, "START PLAYING"); | ||
103 | |||
104 | signed char buf[3000]; | ||
105 | |||
106 | // tick() will do one MIDI clock tick. Then, there's a loop here that | ||
107 | // will generate the right number of samples per MIDI tick. The whole | ||
108 | // MIDI playback is timed in terms of this value.. there are no forced | ||
109 | // delays or anything. It just produces enough samples for each tick, and | ||
110 | // the playback of these samples is what makes the timings right. | ||
111 | // | ||
112 | // This seems to work quite well. | ||
113 | |||
114 | |||
115 | printf("\nOkay, starting sequencing"); | ||
116 | |||
117 | //Tick() will return 0 if there are no more events left to play | ||
118 | while(tick(mf)) | ||
119 | { | ||
120 | |||
121 | //Some annoying math to compute the number of samples | ||
122 | //to syntehsize per each MIDI tick. | ||
123 | bpm=mf->div*1000000/tempo; | ||
124 | nsmp=SAMPLE_RATE/bpm; | ||
125 | |||
126 | //Yes we need to do this math each time because the tempo | ||
127 | //could have changed. | ||
128 | |||
129 | // On second thought, this can be moved to the event that | ||
130 | //recalculates the tempo, to save a little bit of CPU time. | ||
131 | for(l=0; l<nsmp; l++) | ||
132 | { | ||
133 | int s1, s2; | ||
134 | |||
135 | synthSample(&s1, &s2); | ||
136 | |||
137 | |||
138 | //16-bit audio because, well, it's better | ||
139 | // But really because ALSA's OSS emulation sounds extremely | ||
140 | //noisy and distorted when in 8-bit mode. I still do not know | ||
141 | //why this happens. | ||
142 | buf[bp]=s1&0XFF; // Low byte first | ||
143 | bp++; | ||
144 | buf[bp]=s1>>8; //High byte second | ||
145 | bp++; | ||
146 | |||
147 | buf[bp]=s2&0XFF; // Low byte first | ||
148 | bp++; | ||
149 | buf[bp]=s2>>8; //High byte second | ||
150 | bp++; | ||
151 | |||
152 | |||
153 | //As soon as we produce 2000 bytes of sound, | ||
154 | //write it to the sound card. Why 2000? I have | ||
155 | //no idea. It's 1 AM and I am dead tired. | ||
156 | if(bp>=2000) | ||
157 | { | ||
158 | rb->write(fd, buf, 2000); | ||
159 | bp=0; | ||
160 | } | ||
161 | } | ||
162 | } | ||
163 | |||
164 | // unloadFile(mf); | ||
165 | printf("\n"); | ||
166 | rb->close(fd); | ||
167 | return 0; | ||
168 | } | ||