• R/O
  • SSH
  • HTTPS

mdr: Commit


Commit MetaInfo

Revision102 (tree)
Time2023-10-14 06:58:44
Authormateuszviste

Log Message

added mdr_opl_timbregen() and simplified timbre structs

Change Summary

Incremental Difference

--- trunk/inc/mdr/opl.h (revision 101)
+++ trunk/inc/mdr/opl.h (revision 102)
@@ -28,12 +28,47 @@
2828 #ifndef mdr_opl_h
2929 #define mdr_opl_h
3030
31-struct timbre_t {
32- unsigned long modulator_E862, carrier_E862;
33- unsigned char modulator_40, carrier_40;
31+struct mdr_opl_timbre {
32+ unsigned char mod_ws, car_ws; /* waveform select (0-4), reg Exh */
33+ unsigned char mod_sr, car_sr; /* sustain/release, reg 8xh */
34+ unsigned char mod_ad, car_ad; /* attack/decay, reg 6xh */
35+ unsigned char mod_20, car_20; /* tremolo/vibrato/sustain..., reg 2xh */
36+ unsigned char mod_40, car_40; /* reg 4xh */
3437 unsigned char feedconn;
3538 };
3639
40+struct mdr_opl_timbretemplate {
41+ struct {
42+ unsigned char ws; /* waveform select 0..3 */
43+ unsigned char sustlev; /* sustain level 0..15 */
44+ unsigned char release; /* release level 0..15 */
45+ unsigned char attack; /* attack rate 0..15 */
46+ unsigned char decay; /* decay rate 0..15 */
47+ unsigned char tremolo; /* tremolo flag 0..1 */
48+ unsigned char vibrato; /* vibrato flag 0..1 */
49+ unsigned char sustain; /* sustain flag 0..1 */
50+ unsigned char ksr; /* KSR (envelope scaling) flag 0..1 */
51+ unsigned char mult; /* frequency multiplication factor 0..15 */
52+ unsigned char ksl; /* Key Scale Level 0..3 */
53+ unsigned char outlev; /* output level 0..63 */
54+ } carrier;
55+ struct {
56+ unsigned char ws; /* waveform select 0..3 */
57+ unsigned char sustlev; /* sustain level 0..15 */
58+ unsigned char release; /* release level 0..15 */
59+ unsigned char attack; /* attack rate 0..15 */
60+ unsigned char decay; /* decay rate 0..15 */
61+ unsigned char tremolo; /* tremolo flag 0..1 */
62+ unsigned char vibrato; /* vibrato flag 0..1 */
63+ unsigned char sustain; /* sustain flag 0..1 */
64+ unsigned char ksr; /* KSR (envelope scaling) flag 0..1 */
65+ unsigned char mult; /* frequency multiplication factor 0..15 */
66+ unsigned char ksl; /* Key Scale Level 0..3 */
67+ unsigned char outlev; /* output level 0..63 */
68+ } modultr;
69+ unsigned char feedback;/* FeedBack Modulation Factor 0..7 */
70+ unsigned char conn; /* Synthesis type: 0=FM / 1=Additive */
71+};
3772
3873 /* frequency groups, to be used with mdr_opl_noteon() and mdr_opl_notebend().
3974 * There are 7 frequency groups to choose from. Each group supports a different
@@ -89,8 +124,13 @@
89124 /* loads an instrument described by properties in a timbre_t struct into
90125 * the defined voice channel. The OPL2 chip supports up to 9 voice channels,
91126 * from 0 to 8. The timbre struct can be freed right after this call. */
92-void mdr_opl_loadinstrument(unsigned char voice, const struct timbre_t *timbre);
127+void mdr_opl_loadinstrument(unsigned char voice, const struct mdr_opl_timbre *timbre);
93128
129+/* generate a timbre structure based on a timbre template. this is a
130+ * convenience function meant to provide a human-compatible (more readable)
131+ * way of generating a timbre struct. */
132+int mdr_opl_timbre_gen(struct mdr_opl_timbre *timbre, const struct mdr_opl_timbretemplate *tpl);
133+
94134 /* Triggers a note on selected voice channel.
95135 * freqid is a value between 0 and 1023. The following formula can be used to
96136 * determine the freq number for a given note frequency (Hz) and block:
@@ -116,7 +156,7 @@
116156
117157
118158 /*****************************************************************************
119- * IMF PLAYBACK *
159+ * IMF AUDIO FILES PLAYBACK *
120160 * *
121161 * It is possible to mix IMF playback calls with manual notes, but you must *
122162 * take care to use only voices not used by your IMF audio. Typically games *
@@ -129,11 +169,11 @@
129169 * clock must be an incrementing value that wraps to 0 after 65535.
130170 * the clock speed will control the playback's tempo.
131171 * returns the amount of consumed bytes (4 or 6) */
132-unsigned short mdr_opl_imf_init(void *imf, unsigned short ticks);
172+unsigned short mdr_opl_imf_init(void *imf, unsigned short clock);
133173
134174 /* feeds the IMF playback routine with IMF data. returns the amount of bytes
135175 * that have been consumed. this function must be called repeatedly at a high
136176 * frequency for best playback quality. */
137-unsigned short mdr_opl_imf_play(void *imf, unsigned short imflen, unsigned short ticks);
177+unsigned short mdr_opl_imf_play(void *imf, unsigned short imflen, unsigned short clock);
138178
139179 #endif
--- trunk/opl/opl.c (revision 101)
+++ trunk/opl/opl.c (revision 102)
@@ -87,21 +87,10 @@
8787 if (x != 0) return(-1); /* 00h, and the result of step 7 should be C0h. If both are */
8888 if (y != 0xC0) return(-2); /* ok, an AdLib-compatible board is installed in the computer */
8989
90-#ifdef MDR_OPL3
91- /* is it an OPL3 or just an OPL2? */
92- if ((inp(PORT_CTRL) & 0x06) == 0) opl3 = 1;
93-
94- /* enable OPL3 (if detected) and put it into 36 operators mode */
95- if (opl3 != 0) {
96- mdr_opl_regwr(PORT_CTRL, 0x105, 1); /* enable OPL3 mode (36 operators) */
97- mdr_opl_regwr(PORT_CTRL, 0x104, 0); /* disable four-operator voices */
98- }
99-#endif
100-
10190 mdr_opl_regwr(0x01, 0x20); /* enable Waveform Select */
10291 mdr_opl_regwr(0x04, 0x00); /* turn off timers IRQs */
103- mdr_opl_regwr(0x08, 0x40); /* turn off CSW mode and activate FM synth mode */
104- mdr_opl_regwr(0xBD, 0x00); /* set vibrato/tremolo depth to low, set melodic mode */
92+ mdr_opl_regwr(0x08, 0x00); /* turn off CSW mode and reset the octave split point */
93+ mdr_opl_regwr(0xBD, 0x00); /* set vibrato/tremolo depth to low and set melodic mode */
10594
10695 for (x = 0; x < VOICESCOUNT; x++) {
10796 mdr_opl_regwr(0x20 + op1offsets[x], 0x1); /* set the modulator's multiple to 1 */
@@ -129,11 +118,6 @@
129118 mdr_opl_regwr(0x40 + op1offsets[x], 0x1f);
130119 mdr_opl_regwr(0x40 + op2offsets[x], 0x1f);
131120 }
132-
133-#ifdef MDR_OPL3
134- /* if OPL3, switch the chip back into its default OPL2 mode */
135- if (oplmem->opl3 != 0) mdr_opl_regwr(port, 0x105, 0);
136-#endif
137121 }
138122
139123
@@ -147,40 +131,33 @@
147131 }
148132
149133
150-/* loads an instrument described by properties in a timbre_t struct into
134+/* loads an instrument described by properties in a timbre struct into
151135 * the defined voice channel. The OPL2 chip supports up to 9 voice channels,
152136 * from 0 to 8. The timbre struct can be freed right after this call. */
153-void mdr_opl_loadinstrument(unsigned char voice, const struct timbre_t *timbre) {
137+void mdr_opl_loadinstrument(unsigned char voice, const struct mdr_opl_timbre *timbre) {
154138 /* remember carrier40's KSL value for later volume computations */
155- carr40_cache[voice] = timbre->carrier_40 & 0xC0;
139+ carr40_cache[voice] = timbre->car_40 & 0xC0;
156140
157141 /* KSL (key level scaling) / attenuation */
158- mdr_opl_regwr(0x40 + op1offsets[voice], timbre->modulator_40);
159- mdr_opl_regwr(0x40 + op2offsets[voice], carr40_cache[voice] | 0x3f); /* force volume to 0, it will be reajusted during 'note on' */
142+ mdr_opl_regwr(0x40 + op1offsets[voice], timbre->mod_40);
143+ mdr_opl_regwr(0x40 + op2offsets[voice], timbre->car_40);
160144
161145 /* select waveform on both operators */
162- mdr_opl_regwr(0xE0 + op1offsets[voice], timbre->modulator_E862 >> 24);
163- mdr_opl_regwr(0xE0 + op2offsets[voice], timbre->carrier_E862 >> 24);
146+ mdr_opl_regwr(0xE0 + op1offsets[voice], timbre->mod_ws);
147+ mdr_opl_regwr(0xE0 + op2offsets[voice], timbre->car_ws);
164148
165149 /* sustain / release */
166- mdr_opl_regwr(0x80 + op1offsets[voice], (timbre->modulator_E862 >> 16) & 0xff);
167- mdr_opl_regwr(0x80 + op2offsets[voice], (timbre->carrier_E862 >> 16) & 0xff);
150+ mdr_opl_regwr(0x80 + op1offsets[voice], timbre->mod_sr);
151+ mdr_opl_regwr(0x80 + op2offsets[voice], timbre->car_sr);
168152
169153 /* attack rate / decay */
170- mdr_opl_regwr(0x60 + op1offsets[voice], (timbre->modulator_E862 >> 8) & 0xff);
171- mdr_opl_regwr(0x60 + op2offsets[voice], (timbre->carrier_E862 >> 8) & 0xff);
154+ mdr_opl_regwr(0x60 + op1offsets[voice], timbre->mod_ad);
155+ mdr_opl_regwr(0x60 + op2offsets[voice], timbre->car_ad);
172156
173157 /* AM / vibrato / envelope */
174- mdr_opl_regwr(0x20 + op1offsets[voice], timbre->modulator_E862 & 0xff);
175- mdr_opl_regwr(0x20 + op2offsets[voice], timbre->carrier_E862 & 0xff);
158+ mdr_opl_regwr(0x20 + op1offsets[voice], timbre->mod_20);
159+ mdr_opl_regwr(0x20 + op2offsets[voice], timbre->car_20);
176160
177-#ifdef MDR_OPL3
178- if (oplmem->opl3 != 0) { /* on OPL3 make sure to enable LEFT/RIGHT unmute bits */
179- mdr_opl_regwr(oplport, 0xC0 + voice, timbre->feedconn | 0x30);
180- return;
181- }
182-#endif
183-
184161 mdr_opl_regwr(0xC0 + voice, timbre->feedconn);
185162 }
186163
--- trunk/opl/opltigen.c (nonexistent)
+++ trunk/opl/opltigen.c (revision 102)
@@ -0,0 +1,58 @@
1+/*
2+ * OPL2 timbre-building function
3+ *
4+ * This file is part of the Mateusz' DOS Routines (MDR): http://mdr.osdn.io
5+ * Published under the terms of the MIT License, as stated below.
6+ *
7+ * Copyright (C) 2015-2023 Mateusz Viste
8+ *
9+ * Permission is hereby granted, free of charge, to any person obtaining a copy
10+ * of this software and associated documentation files (the "Software"), to
11+ * deal in the Software without restriction, including without limitation the
12+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
13+ * sell copies of the Software, and to permit persons to whom the Software is
14+ * furnished to do so, subject to the following conditions:
15+ *
16+ * The above copyright notice and this permission notice shall be included in
17+ * all copies or substantial portions of the Software.
18+ *
19+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25+ * IN THE SOFTWARE.
26+ */
27+
28+#include <mdr/opl.h>
29+
30+/* generate a timbre structure based on a timbre template. this is a
31+ * convenience function meant to provide a human-compatible (more readable)
32+ * way of generating a timbre struct. */
33+int mdr_opl_timbre_gen(struct mdr_opl_timbre *timbre, const struct mdr_opl_timbretemplate *tpl) {
34+ /* wave selector */
35+ timbre->car_ws = tpl->carrier.ws;
36+ timbre->mod_ws = tpl->modultr.ws;
37+
38+ /* sustain / release */
39+ timbre->car_sr = (tpl->carrier.sustain << 4) | tpl->carrier.release;
40+ timbre->mod_sr = (tpl->modultr.sustain << 4) | tpl->modultr.release;
41+
42+ /* attack / decay */
43+ timbre->car_ad = (tpl->carrier.attack << 4) | tpl->carrier.decay;
44+ timbre->mod_ad = (tpl->modultr.attack << 4) | tpl->modultr.decay;
45+
46+ /* Tremolo / Vibrato / Sustain / KSR / Frequency Multiplication Factor */
47+ timbre->car_20 = (tpl->carrier.tremolo << 7) | (tpl->carrier.vibrato << 6) | (tpl->carrier.sustain << 5) | (tpl->carrier.ksr << 4) | (tpl->carrier.mult);
48+ timbre->mod_20 = (tpl->modultr.tremolo << 7) | (tpl->modultr.vibrato << 6) | (tpl->modultr.sustain << 5) | (tpl->modultr.ksr << 4) | (tpl->modultr.mult);
49+
50+ /* Key Scale Level / Output Level */
51+ timbre->car_40 = (tpl->carrier.ksl << 6) | tpl->carrier.outlev;
52+ timbre->mod_40 = (tpl->modultr.ksl << 6) | tpl->modultr.outlev;
53+
54+ /* Feedback / Connection */
55+ timbre->feedconn = (tpl->feedback << 1) | tpl->conn;
56+
57+ return(0);
58+}
Show on old repository browser