1 /*
2  * sample.c -- Midi Wavetable Processing library
3  *
4  * Copyright (C) WildMIDI Developers 2001-2016
5  *
6  * This file is part of WildMIDI.
7  *
8  * WildMIDI is free software: you can redistribute and/or modify the player
9  * under the terms of the GNU General Public License and you can redistribute
10  * and/or modify the library under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation, either version 3 of
12  * the licenses, or(at your option) any later version.
13  *
14  * WildMIDI is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License and
17  * the GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License and the
20  * GNU Lesser General Public License along with WildMIDI.  If not,  see
21  * <http://www.gnu.org/licenses/>.
22  */
23 
24 #include "config.h"
25 
26 #include <stdio.h>
27 #include <stdint.h>
28 
29 #include "lock.h"
30 #include "common.h"
31 #include "patches.h"
32 #include "gus_pat.h"
33 #include "wildmidi_lib.h"
34 #include "internal_midi.h"
35 #include "sample.h"
36 
37 /*
38  FIXME: Need to decide if this stuff needs to be broken up for different formats.
39  */
40 
_WM_get_decay_samples(struct _mdi * mdi,uint8_t channel,uint8_t note)41 uint32_t _WM_get_decay_samples(struct _mdi * mdi, uint8_t channel, uint8_t note) {
42     struct _patch *patch = NULL;
43     struct _sample *sample = NULL;
44     uint32_t freq = 0;
45     uint32_t decay_samples = 0;
46 
47     if (mdi->channel[channel].isdrum) {
48         patch = _WM_get_patch_data(mdi,
49                                    ((mdi->channel[channel].bank << 8)
50                                     | note | 0x80));
51     } else {
52         patch = mdi->channel[channel].patch;
53     }
54 
55     if (patch == NULL) return (0);
56 
57     /* first get the freq we need so we can check the right sample */
58     if (patch->patchid & 0x80) {
59         /* is a drum patch */
60         if (patch->note) {
61             freq = _WM_freq_table[(patch->note % 12) * 100]
62                                               >> (10 - (patch->note / 12));
63         } else {
64             freq = _WM_freq_table[(note % 12) * 100] >> (10 - (note / 12));
65         }
66     } else {
67         freq = _WM_freq_table[(note % 12) * 100] >> (10 - (note / 12));
68     }
69 
70     /* get the sample */
71     sample = _WM_get_sample_data(patch, (freq / 100));
72     if (sample == NULL) return (0);
73 
74     decay_samples = sample->note_off_decay;
75 
76     return (decay_samples);
77 }
78 
79 
_WM_get_sample_data(struct _patch * sample_patch,uint32_t freq)80 struct _sample *_WM_get_sample_data(struct _patch *sample_patch, uint32_t freq) {
81     struct _sample *last_sample = NULL;
82     struct _sample *return_sample = NULL;
83 
84     _WM_Lock(&_WM_patch_lock);
85     if (sample_patch == NULL) {
86         _WM_Unlock(&_WM_patch_lock);
87         return (NULL);
88     }
89     if (sample_patch->first_sample == NULL) {
90         _WM_Unlock(&_WM_patch_lock);
91         return (NULL);
92     }
93     if (freq == 0) {
94         _WM_Unlock(&_WM_patch_lock);
95         return (sample_patch->first_sample);
96     }
97 
98     return_sample = sample_patch->first_sample;
99     last_sample = sample_patch->first_sample;
100     while (last_sample) {
101         if (freq > last_sample->freq_low) {
102             if (freq < last_sample->freq_high) {
103                 _WM_Unlock(&_WM_patch_lock);
104                 return (last_sample);
105             } else {
106                 return_sample = last_sample;
107             }
108         }
109         last_sample = last_sample->next;
110     }
111     _WM_Unlock(&_WM_patch_lock);
112     return (return_sample);
113 }
114 
115 /* sample loading */
116 
117 int
_WM_load_sample(struct _patch * sample_patch)118 _WM_load_sample(struct _patch *sample_patch) {
119     struct _sample *guspat = NULL;
120     struct _sample *tmp_sample = NULL;
121     uint32_t i = 0;
122 
123     /* we only want to try loading the guspat once. */
124     sample_patch->loaded = 1;
125 
126     if ((guspat = _WM_load_gus_pat(sample_patch->filename, _WM_fix_release)) == NULL) {
127         return (-1);
128     }
129 
130     if (_WM_auto_amp) {
131         int16_t tmp_max = 0;
132         int16_t tmp_min = 0;
133         int16_t samp_max = 0;
134         int16_t samp_min = 0;
135         tmp_sample = guspat;
136         do {
137             samp_max = 0;
138             samp_min = 0;
139             for (i = 0; i < (tmp_sample->data_length >> 10); i++) {
140                 if (tmp_sample->data[i] > samp_max)
141                     samp_max = tmp_sample->data[i];
142                 if (tmp_sample->data[i] < samp_min)
143                     samp_min = tmp_sample->data[i];
144             }
145             if (samp_max > tmp_max)
146                 tmp_max = samp_max;
147             if (samp_min < tmp_min)
148                 tmp_min = samp_min;
149             tmp_sample = tmp_sample->next;
150         } while (tmp_sample);
151         if (_WM_auto_amp_with_amp) {
152             if (tmp_max >= -tmp_min) {
153                 sample_patch->amp = (sample_patch->amp
154                                      * ((32767 << 10) / tmp_max)) >> 10;
155             } else {
156                 sample_patch->amp = (sample_patch->amp
157                                      * ((32768 << 10) / -tmp_min)) >> 10;
158             }
159         } else {
160             if (tmp_max >= -tmp_min) {
161                 sample_patch->amp = (32767 << 10) / tmp_max;
162             } else {
163                 sample_patch->amp = (32768 << 10) / -tmp_min;
164             }
165         }
166     }
167 
168     sample_patch->first_sample = guspat;
169 
170     if (sample_patch->patchid & 0x0080) {
171         if (!(sample_patch->keep & SAMPLE_LOOP)) {
172             do {
173                 guspat->modes &= 0xFB;
174                 guspat = guspat->next;
175             } while (guspat);
176         }
177         guspat = sample_patch->first_sample;
178         if (!(sample_patch->keep & SAMPLE_ENVELOPE)) {
179             do {
180                 guspat->modes &= 0xBF;
181                 guspat = guspat->next;
182             } while (guspat);
183         }
184         guspat = sample_patch->first_sample;
185     }
186 
187     if (sample_patch->patchid == 47) {
188         do {
189             if (!(guspat->modes & SAMPLE_LOOP)) {
190                 for (i = 3; i < 6; i++) {
191                     guspat->env_target[i] = guspat->env_target[2];
192                     guspat->env_rate[i] = guspat->env_rate[2];
193                 }
194             }
195             guspat = guspat->next;
196         } while (guspat);
197         guspat = sample_patch->first_sample;
198     }
199 
200     do {
201         if ((sample_patch->remove & SAMPLE_SUSTAIN)
202             && (guspat->modes & SAMPLE_SUSTAIN)) {
203             guspat->modes ^= SAMPLE_SUSTAIN;
204         }
205         if ((sample_patch->remove & SAMPLE_CLAMPED)
206             && (guspat->modes & SAMPLE_CLAMPED)) {
207             guspat->modes ^= SAMPLE_CLAMPED;
208         }
209         if (sample_patch->keep & SAMPLE_ENVELOPE) {
210             guspat->modes |= SAMPLE_ENVELOPE;
211         }
212 
213         for (i = 0; i < 6; i++) {
214             if (guspat->modes & SAMPLE_ENVELOPE) {
215                 if (sample_patch->env[i].set & 0x02) {
216                     guspat->env_target[i] = 16448
217                                                 * (int32_t) (255.0f * sample_patch->env[i].level);
218                 }
219                 if (sample_patch->env[i].set & 0x01) {
220                     guspat->env_rate[i] = (int32_t) (4194303.0f
221                                                      / ((float) _WM_SampleRate
222                                                         * (sample_patch->env[i].time / 1000.0f)));
223                 }
224             } else {
225                 guspat->env_target[i] = 4194303;
226                 guspat->env_rate[i] = (int32_t) (4194303.0f
227                                                  / ((float) _WM_SampleRate * env_time_table[63]));
228             }
229         }
230 
231         guspat = guspat->next;
232     } while (guspat);
233     return (0);
234 }
235