Added loading of SBI files.

(e.g. from http://cd.textfiles.com/soundsensations/SYNTH/SBINS/ )
This commit is contained in:
Raine M. Ekman
2015-01-11 19:19:52 +02:00
parent 925122545e
commit 63e23e0158
2 changed files with 114 additions and 12 deletions

View File

@@ -50,6 +50,9 @@
#include "InstrumentTrack.h"
#include <QDomDocument>
#include <QFile>
#include <QFileInfo>
#include <QByteArray>
#include "opl.h"
#include "temuopl.h"
@@ -76,7 +79,7 @@ Plugin::Descriptor PLUGIN_EXPORT OPL2_plugin_descriptor =
0x0100,
Plugin::Instrument,
new PluginPixmapLoader( "logo" ),
NULL,
"sbi",
NULL
};
@@ -158,6 +161,8 @@ opl2instrument::opl2instrument( InstrumentTrack * _instrument_track ) :
voiceLRU[i] = i;
}
storedname = displayName();
updatePatch();
// Can the buffer size change suddenly? I bet that would break lots of stuff
@@ -166,7 +171,7 @@ opl2instrument::opl2instrument( InstrumentTrack * _instrument_track ) :
// Some kind of sane defaults
pitchbend = 0;
pitchBendRange = 100;
pitchBendRange = 100; // cents
RPNcoarse = RPNfine = 255;
tuneEqual(69, 440);
@@ -338,10 +343,8 @@ bool opl2instrument::handleMidiEvent( const MidiEvent& event, const MidiTime& ti
break;
case MidiPitchBend:
// Update fnumber table
// Pitchbend should be in the range 0...16383 but the new range knob gets it wrong.
// tmp_pb = (2*BEND_CENTS)*((float)event.m_data.m_param[0]/16383)-BEND_CENTS;
// Something like 100 cents = 8192, but offset by 8192 so the +/-100 cents range goes from 0...16383?
// Neutral = 8192, full downbend = 0, full upbend = 16383
tmp_pb = ( event.pitchBend()-8192 ) * pitchBendRange / 8192;
if( tmp_pb != pitchbend ) {
@@ -377,7 +380,10 @@ bool opl2instrument::handleMidiEvent( const MidiEvent& event, const MidiTime& ti
}
break;
default:
#ifdef LMMS_DEBUG
printf("Midi event type %d\n",event.type());
#endif
break;
}
emulatorMutex.unlock();
return true;
@@ -528,11 +534,6 @@ void opl2instrument::loadGMPatch() {
loadPatch(inst);
}
//
/* void opl2instrument::loadSBIFile() {
} */
// Update patch from the models to the chip emulation
void opl2instrument::updatePatch() {
unsigned char inst[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
@@ -546,9 +547,9 @@ void opl2instrument::updatePatch() {
( op2_perc_mdl.value() ? 0 : 32 ) + // NB. This envelope mode is "perc", not "sus"
( op2_ksr_mdl.value() ? 16 : 0 ) +
((int)op2_mul_mdl.value() & 0x0f);
inst[2] = ( (int)op1_scale_mdl.value() & 0x03 << 6 ) +
inst[2] = ( ((int)op1_scale_mdl.value() & 0x03) << 6 ) +
(63 - ( (int)op1_lvl_mdl.value() & 0x3f ) );
inst[3] = ( (int)op2_scale_mdl.value() & 0x03 << 6 ) +
inst[3] = ( ((int)op2_scale_mdl.value() & 0x03) << 6 ) +
(63 - ( (int)op2_lvl_mdl.value() & 0x3f ) );
inst[4] = ((15 - ((int)op1_a_mdl.value() & 0x0f ) ) << 4 )+
(15 - ( (int)op1_d_mdl.value() & 0x0f ) );
@@ -577,9 +578,108 @@ void opl2instrument::updatePatch() {
setVoiceVelocity(voice, velocities[voiceNote[voice]] );
}
}
#ifdef LMMS_DEBUG
printf("UPD: %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x\n",
inst[0], inst[1], inst[2], inst[3], inst[4],
inst[5], inst[6], inst[7], inst[8], inst[9], inst[10]);
#endif
loadPatch(inst);
}
// Load an SBI file into the knob models
void opl2instrument::loadFile( const QString& file ) {
// http://cd.textfiles.com/soundsensations/SYNTH/SBINS/
// http://cd.textfiles.com/soundsensations/SYNTH/SBI1198/1198SBI.ZIP
if( !file.isEmpty() && QFileInfo( file ).exists() )
{
QFile sbifile(file);
if (!sbifile.open(QIODevice::ReadOnly )) {
printf("Can't open file\n");
return;
}
QByteArray sbidata = sbifile.read(52);
if( !sbidata.startsWith("SBI\0x1a") ) {
printf("No SBI signature\n");
return;
}
if( sbidata.size() != 52 ) {
printf("SBI size error: expected 52, got %d\n",sbidata.size() );
}
// Minimum size of SBI if we ignore "reserved" bytes at end
// https://courses.engr.illinois.edu/ece390/resources/sound/cmf.txt.html
if( sbidata.size() < 47 ) {
return;
}
// If user has changed track name... let's hope my logic is valid.
QString sbiname = sbidata.mid(4, 32);
if( instrumentTrack()->displayName() == storedname ) {
instrumentTrack()->setName(sbiname);
storedname = sbiname;
}
#ifdef LMMS_DEBUG
printf("SBI: %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x\n",
(unsigned char)sbidata[36], (unsigned char)sbidata[37], (unsigned char)sbidata[38], (unsigned char)sbidata[39], (unsigned char)sbidata[40],
(unsigned char)sbidata[41], (unsigned char)sbidata[42], (unsigned char)sbidata[43], (unsigned char)sbidata[44], (unsigned char)sbidata[45], (unsigned char)sbidata[46]);
#endif
// Modulator Sound Characteristic (Mult, KSR, EG, VIB, AM)
op1_trem_mdl.setValue( (sbidata[36] & 0x80 ) == 0x80 ? true : false );
op1_vib_mdl.setValue( (sbidata[36] & 0x40 ) == 0x40 ? true : false );
op1_perc_mdl.setValue( (sbidata[36] & 0x20 ) == 0x20 ? false : true );
op1_ksr_mdl.setValue( (sbidata[36] & 0x10 ) == 0x10 ? true : false );
op1_mul_mdl.setValue( sbidata[36] & 0x0f );
// Carrier Sound Characteristic
op2_trem_mdl.setValue( (sbidata[37] & 0x80 ) == 0x80 ? true : false );
op2_vib_mdl.setValue( (sbidata[37] & 0x40 ) == 0x40 ? true : false );
op2_perc_mdl.setValue( (sbidata[37] & 0x20 ) == 0x20 ? false : true );
op2_ksr_mdl.setValue( (sbidata[37] & 0x10 ) == 0x10 ? true : false );
op2_mul_mdl.setValue( sbidata[37] & 0x0f );
// Modulator Scaling/Output Level
op1_scale_mdl.setValue( (sbidata[38] & 0xc0 ) >> 6 );
op1_lvl_mdl.setValue( 63 - (sbidata[38] & 0x3f) );
// Carrier Scaling/Output Level
op2_scale_mdl.setValue( (sbidata[39] & 0xc0) >> 6 );
op2_lvl_mdl.setValue( 63 - (sbidata[39] & 0x3f) );
// Modulator Attack/Decay
op1_a_mdl.setValue( 15 - ( ( sbidata[40] & 0xf0 ) >> 4 ) );
op1_d_mdl.setValue( 15 - ( sbidata[40] & 0x0f ) );
// Carrier Attack/Decay
op2_a_mdl.setValue( 15 - ( ( sbidata[41] & 0xf0 ) >> 4 ) );
op2_d_mdl.setValue( 15 - ( sbidata[41] & 0x0f ) );
// Modulator Sustain/Release
op1_s_mdl.setValue( 15 - ( ( sbidata[42] & 0xf0 ) >> 4 ) );
op1_r_mdl.setValue( 15 - ( sbidata[42] & 0x0f ) );
// Carrier Sustain/Release
op2_s_mdl.setValue( 15 - ( ( sbidata[43] & 0xf0 ) >> 4 ) );
op2_r_mdl.setValue( 15 - ( sbidata[43] & 0x0f ) );
// Modulator Wave Select
op1_waveform_mdl.setValue( sbidata[44] & 0x03 );
// Carrier Wave Select
op2_waveform_mdl.setValue( sbidata[45] & 0x03 );
// Feedback/Connection
fm_mdl.setValue( (sbidata[46] & 0x01) == 0x01 ? false : true );
feedback_mdl.setValue( ( (sbidata[46] & 0x0e ) >> 1 ) );
}
}
opl2instrumentView::opl2instrumentView( Instrument * _instrument,

View File

@@ -63,6 +63,7 @@ public:
void loadSettings( const QDomElement & _this );
void loadPatch(const unsigned char inst[14]);
void tuneEqual(int center, float Hz);
virtual void loadFile( const QString& file );
IntModel m_patchModel;
@@ -114,6 +115,7 @@ private slots:
private:
Copl *theEmulator;
QString storedname;
fpp_t frameCount;
short *renderbuffer;
int voiceNote[9];