add bank loader port from C (TMB)
This commit is contained in:
parent
c704acbaa1
commit
114fbdfde1
2 changed files with 511 additions and 504 deletions
|
@ -51,12 +51,7 @@ typedef struct {
|
|||
} bank_instr;
|
||||
*/
|
||||
|
||||
//#define STR_BNK_WRITERR "Fehler beim Schreiben nach Bank-Datei '%s': "
|
||||
//#define STR_BNK_PARSERR "Fehler beim Verarbeiten von Bank-Datei '%s': "
|
||||
//#define STR_BNK_EIO STR_BNK_READERR "E/A-Fehler"
|
||||
//#define STR_BNK_EEOF STR_BNK_READERR "Ende der Datei erreicht"
|
||||
//#define STR_BNK_EWIO STR_BNK_WRITERR "E/A-Fehler"
|
||||
//#define STR_BNK_EEOD STR_BNK_PARSERR "Ende der Daten erreicht"
|
||||
//#define STR_BNK_EEOD "Fehler beim Verarbeiten von Bank-Datei '%s': Ende der Daten erreicht"
|
||||
|
||||
private static byte[] bnk_read_mhbank(byte[] raw, String filename, int minsize, int maxsize, byte[] hdr) {
|
||||
int size = raw.length;
|
||||
|
@ -171,12 +166,54 @@ typedef struct {
|
|||
}
|
||||
return instr;
|
||||
}
|
||||
|
||||
|
||||
private static Instrument tmb_read_instr(byte[] data, int offset, boolean drum) {
|
||||
Operator[] ops = new Operator[2];
|
||||
int transpose = drum ? 0 : (int)((byte)data[11]);
|
||||
for(int op = 0; op < 2; op++) {
|
||||
boolean tremolo = (data[op+0] & 0x80) != 0;
|
||||
boolean vibrato = (data[op+0] & 0x40) != 0;
|
||||
boolean sustaining = (data[op+0] & 0x20) != 0;
|
||||
boolean ksr = (data[op+0] & 0x10) != 0;
|
||||
int mult = data[op+0] & 0x0f;
|
||||
int attack = ((data[op+4] & 255) >> 4) & 0x0f;
|
||||
int decay = data[op+4] & 0x0f;
|
||||
int sustain = ((data[op+6] & 255) >> 4) & 0x0f;
|
||||
int release = data[op+6] & 0x0f;
|
||||
int waveform = data[op+8] & 0x07;
|
||||
int ksl = ((data[op+2] & 255) >> 6) & 0x03;
|
||||
int level = data[op+2] & 0x3f;
|
||||
ops[op] = new Operator(mult, level, waveform, attack, decay, sustain, release, tremolo, vibrato, sustaining, ksr, ksl, transpose, 0);
|
||||
}
|
||||
Instrument ins = new Instrument((data[10] >> 1) & 0x07, 0, data[10] & 0x01, ops);
|
||||
if(drum)
|
||||
ins.setFixed(data[11] & 0x7f);
|
||||
return ins;
|
||||
}
|
||||
|
||||
private static Instrument[] tmb_read_bank(byte[] raw, String filename) {
|
||||
byte[] data = bnk_read_sbank(raw, filename, 256 * 13);
|
||||
if(data == null)
|
||||
return null;
|
||||
Instrument[] instr = new Instrument[256];
|
||||
int offset = 0;
|
||||
for(int i = 0; i < 256; i++) {
|
||||
instr[i] = tmb_read_instr(data, offset, i >= 128);
|
||||
offset += 13;
|
||||
}
|
||||
return instr;
|
||||
}
|
||||
|
||||
/*
|
||||
private static void tmb_read_instr(bank_instr *instr, uint8_t *data, uint8_t drum) {
|
||||
instr->name[0] = 0;
|
||||
private static Instrument sb_read_instr(bank_instr *instr, uint8_t *data, uint8_t drum) {
|
||||
for(int h = 0; h < 28; h++) {
|
||||
instr->name[h] = (data[h] == 0x1a) ? ' ' : data[h];
|
||||
}
|
||||
instr->name[28] = 0;
|
||||
instr->percnum = data[35] & 0x7f;
|
||||
instr->fixed = drum;
|
||||
instr->op = b_op2;
|
||||
data += 36;
|
||||
for(int op = 0; op < 2; op++) {
|
||||
instr->channels[0].ops[op].tremolo = (data[op+0] & 0x80) > 0;
|
||||
instr->channels[0].ops[op].vibrato = (data[op+0] & 0x40) > 0;
|
||||
|
@ -193,27 +230,444 @@ typedef struct {
|
|||
}
|
||||
instr->channels[0].feedback = (data[10] >> 1) & 0x07;
|
||||
instr->channels[0].am = data[10] & 0x01;
|
||||
instr->percnum = drum ? (data[11] & 0x7f) : 0;
|
||||
instr->channels[0].offset = drum ? 0 : ((int8_t)data[11]);
|
||||
instr->channels[0].offset = 0;
|
||||
instr->channels[0].detune = 0;
|
||||
}
|
||||
|
||||
bank_instr *tmb_read_bank(const char *filename) {
|
||||
private static Instrument[] sb_read_bank(byte[] raw, String filename, boolean drum) {
|
||||
uint8_t *data;
|
||||
bank_instr *instr;
|
||||
uint32_t size = bnk_read_sbank(&data, &instr, filename, 256*13);
|
||||
uint32_t size = bnk_read_sbank(&data, &instr, filename, 128*52);
|
||||
if(size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
uint8_t *odata = data;
|
||||
for(int i = 0; i < 256; i++) {
|
||||
tmb_read_instr(&instr[i], data, i >= 128);
|
||||
data += 13;
|
||||
for(int i = 0; i < 128; i++) {
|
||||
instr[i + (drum ? 0 : 128)].op = b_op0;
|
||||
instr[i + (drum ? 0 : 128)].name[0] = 0;
|
||||
}
|
||||
for(int i = 0; i < 128; i++) {
|
||||
sb_read_instr(&instr[i + (drum ? 128 : 0)], data, drum);
|
||||
data += 52;
|
||||
}
|
||||
free(odata);
|
||||
return instr;
|
||||
}
|
||||
|
||||
private static Instrument sb3_read_instr(bank_instr *instr, uint8_t *data, uint8_t drum) {
|
||||
for(int h = 0; h < 28; h++) {
|
||||
instr->name[h] = (data[h] == 0x1a) ? ' ' : data[h];
|
||||
}
|
||||
instr->name[28] = 0;
|
||||
instr->percnum = data[35] & 0x7f;
|
||||
instr->fixed = drum;
|
||||
instr->op = (data[0] == '4') ? b_op4 : b_op2;
|
||||
data += 36;
|
||||
for(int ch = 0; ch < 2; ch++) {
|
||||
for(int op = 0; op < 2; op++) {
|
||||
instr->channels[ch].ops[op].tremolo = (data[op+0] & 0x80) > 0;
|
||||
instr->channels[ch].ops[op].vibrato = (data[op+0] & 0x40) > 0;
|
||||
instr->channels[ch].ops[op].sustaining = (data[op+0] & 0x20) > 0;
|
||||
instr->channels[ch].ops[op].ksr = (data[op+0] & 0x10) > 0;
|
||||
instr->channels[ch].ops[op].mult = data[op+0] & 0x0f;
|
||||
instr->channels[ch].ops[op].attack = (data[op+4] >> 4) & 0x0f;
|
||||
instr->channels[ch].ops[op].decay = data[op+4] & 0x0f;
|
||||
instr->channels[ch].ops[op].sustain = (data[op+6] >> 4) & 0x0f;
|
||||
instr->channels[ch].ops[op].release = data[op+6] & 0x0f;
|
||||
instr->channels[ch].ops[op].waveform = data[op+8] & 0x07;
|
||||
instr->channels[ch].ops[op].ksl = (data[op+2] >> 6) & 0x03;
|
||||
instr->channels[ch].ops[op].level = data[op+2] & 0x3f;
|
||||
}
|
||||
instr->channels[ch].feedback = (data[10] >> 1) & 0x07;
|
||||
instr->channels[ch].am = data[10] & 0x01;
|
||||
instr->channels[ch].offset = 0;
|
||||
instr->channels[ch].detune = 0;
|
||||
data += 11;
|
||||
}
|
||||
}
|
||||
|
||||
private static Instrument[] sb3_read_bank(byte[] raw, String filename, boolean drum) {
|
||||
uint8_t *data;
|
||||
bank_instr *instr;
|
||||
uint32_t size = bnk_read_sbank(&data, &instr, filename, 128*60);
|
||||
if(size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
uint8_t *odata = data;
|
||||
for(int i = 0; i < 128; i++) {
|
||||
instr[i + (drum ? 0 : 128)].op = b_op0;
|
||||
instr[i + (drum ? 0 : 128)].name[0] = 0;
|
||||
}
|
||||
for(int i = 0; i < 128; i++) {
|
||||
sb3_read_instr(&instr[i + (drum ? 128 : 0)], data, drum);
|
||||
data += 60;
|
||||
}
|
||||
free(odata);
|
||||
return instr;
|
||||
}
|
||||
|
||||
private static Instrument op3_read_instr(bank_instr *instr, uint8_t *data, uint8_t drum) {
|
||||
instr->percnum = data[1] & 0x7f;
|
||||
instr->fixed = drum;
|
||||
instr->op = ((data[0] & 0x01) > 0) ? b_op4 : b_op2;
|
||||
data += 2;
|
||||
for(int ch = 0; ch < 2; ch++) {
|
||||
for(int op = 0; op < 2; op++) {
|
||||
instr->channels[ch].ops[op].tremolo = (data[op*6+0] & 0x80) > 0;
|
||||
instr->channels[ch].ops[op].vibrato = (data[op*6+0] & 0x40) > 0;
|
||||
instr->channels[ch].ops[op].sustaining = (data[op*6+0] & 0x20) > 0;
|
||||
instr->channels[ch].ops[op].ksr = (data[op*6+0] & 0x10) > 0;
|
||||
instr->channels[ch].ops[op].mult = data[op*6+0] & 0x0f;
|
||||
instr->channels[ch].ops[op].attack = (data[op*6+2] >> 4) & 0x0f;
|
||||
instr->channels[ch].ops[op].decay = data[op*6+2] & 0x0f;
|
||||
instr->channels[ch].ops[op].sustain = (data[op*6+3] >> 4) & 0x0f;
|
||||
instr->channels[ch].ops[op].release = data[op*6+3] & 0x0f;
|
||||
instr->channels[ch].ops[op].waveform = data[op*6+4] & 0x07;
|
||||
instr->channels[ch].ops[op].ksl = (data[op*6+1] >> 6) & 0x03;
|
||||
instr->channels[ch].ops[op].level = data[op*6+1] & 0x3f;
|
||||
}
|
||||
instr->channels[ch].feedback = (data[5] >> 1) & 0x07;
|
||||
instr->channels[ch].am = data[5] & 0x01;
|
||||
instr->channels[ch].offset = 0;
|
||||
instr->channels[ch].detune = 0;
|
||||
data += 11;
|
||||
}
|
||||
}
|
||||
|
||||
private static Instrument[] op3_read_bank(byte[] raw, String filename) {
|
||||
uint8_t *data;
|
||||
bank_instr *instr;
|
||||
uint32_t size = bnk_read_mhbank(&data, &instr, filename, 16, 256*24+16, "Junglevision Patch File\x1a", 24);
|
||||
if(size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
uint8_t *odata = data;
|
||||
for(int i = 0; i < 256; i++) {
|
||||
instr[i].op = b_op0;
|
||||
instr[i].name[0] = 0;
|
||||
}
|
||||
data += 8;
|
||||
uint16_t nmelo = dmx_read_uint16(&data[0]);
|
||||
uint16_t ndrum = dmx_read_uint16(&data[2]);
|
||||
uint16_t omelo = dmx_read_uint16(&data[4]);
|
||||
uint16_t odrum = dmx_read_uint16(&data[6]);
|
||||
data += 8;
|
||||
if((((nmelo+ndrum)*24+16) > size) || ((omelo+nmelo) > 128) || ((odrum+ndrum) > 128)) {
|
||||
fprintf(stderr, STR_BNK_EEOD"\n", filename);
|
||||
free(odata);
|
||||
free(instr);
|
||||
return NULL;
|
||||
}
|
||||
for(int i = 0; i < nmelo; i++) {
|
||||
op3_read_instr(&instr[i + omelo], data, 0);
|
||||
data += 24;
|
||||
}
|
||||
for(int i = 0; i < ndrum; i++) {
|
||||
op3_read_instr(&instr[i + odrum + 128], data, 1);
|
||||
data += 24;
|
||||
}
|
||||
free(odata);
|
||||
return instr;
|
||||
}
|
||||
|
||||
private static Instrument ad_read_instr(bank_instr *instr, uint8_t *data, uint8_t drum, uint16_t isize) {
|
||||
if(isize < 12) {
|
||||
return;
|
||||
}
|
||||
instr->percnum = data[0] & 0x7f;
|
||||
instr->fixed = drum;
|
||||
instr->op = (isize >= 23) ? b_op4 : b_op2;
|
||||
data += 1;
|
||||
instr->channels[0].feedback = instr->channels[1].feedback = (data[5] >> 1) & 0x07;
|
||||
instr->channels[0].am = data[5] & 0x01;
|
||||
instr->channels[1].am = (data[5] & 0x80) > 0;
|
||||
for(int ch = 0; ch < ((isize >= 23) ? 2 : 1); ch++) {
|
||||
for(int op = 0; op < 2; op++) {
|
||||
instr->channels[ch].ops[op].tremolo = (data[op*6+0] & 0x80) > 0;
|
||||
instr->channels[ch].ops[op].vibrato = (data[op*6+0] & 0x40) > 0;
|
||||
instr->channels[ch].ops[op].sustaining = (data[op*6+0] & 0x20) > 0;
|
||||
instr->channels[ch].ops[op].ksr = (data[op*6+0] & 0x10) > 0;
|
||||
instr->channels[ch].ops[op].mult = data[op*6+0] & 0x0f;
|
||||
instr->channels[ch].ops[op].attack = (data[op*6+2] >> 4) & 0x0f;
|
||||
instr->channels[ch].ops[op].decay = data[op*6+2] & 0x0f;
|
||||
instr->channels[ch].ops[op].sustain = (data[op*6+3] >> 4) & 0x0f;
|
||||
instr->channels[ch].ops[op].release = data[op*6+3] & 0x0f;
|
||||
instr->channels[ch].ops[op].waveform = data[op*6+4] & 0x07;
|
||||
instr->channels[ch].ops[op].ksl = (data[op*6+1] >> 6) & 0x03;
|
||||
instr->channels[ch].ops[op].level = data[op*6+1] & 0x3f;
|
||||
}
|
||||
instr->channels[ch].offset = 0;
|
||||
instr->channels[ch].detune = 0;
|
||||
data += 11;
|
||||
}
|
||||
}
|
||||
|
||||
private static Instrument[] ad_read_bank(byte[] raw, String filename) {
|
||||
uint8_t *data;
|
||||
bank_instr *instr;
|
||||
uint32_t size = bnk_read_mbank(&data, &instr, filename, 2, 256*20+2);
|
||||
if(size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
uint8_t *odata = data;
|
||||
for(int i = 0; i < 256; i++) {
|
||||
instr[i].op = b_op0;
|
||||
instr[i].name[0] = 0;
|
||||
}
|
||||
for(int i = 0;; i++, data += 6) {
|
||||
if((i*6) >= size) {
|
||||
fprintf(stderr, STR_BNK_EEOD"\n", filename);
|
||||
free(odata);
|
||||
free(instr);
|
||||
return NULL;
|
||||
}
|
||||
uint8_t prog = data[0];
|
||||
if(prog == 0xff) {
|
||||
break;
|
||||
}
|
||||
if(prog >= 128) {
|
||||
continue;
|
||||
}
|
||||
uint8_t bank = data[1];
|
||||
if((bank != 0) && (bank != 127)) {
|
||||
continue;
|
||||
}
|
||||
uint16_t offs = dmx_read_uint16(data+2);
|
||||
uint16_t isize;
|
||||
if(((offs+2) > size) || ((offs+(isize = dmx_read_uint16(odata+offs))) > size) || (isize < 2)) {
|
||||
fprintf(stderr, STR_BNK_EEOD"\n", filename);
|
||||
free(odata);
|
||||
free(instr);
|
||||
return NULL;
|
||||
}
|
||||
ad_read_instr(&instr[prog + ((bank == 127) ? 128 : 0)], odata+(offs+2), bank == 127, isize-2);
|
||||
}
|
||||
free(odata);
|
||||
return instr;
|
||||
}
|
||||
|
||||
private static Instrument bk_read_instr(bank_instr *instr, uint8_t *data, uint8_t drum) {
|
||||
instr->fixed = drum;
|
||||
instr->op = b_op2;
|
||||
for(int op = 0; op < 2; op++) {
|
||||
instr->channels[0].ops[op].tremolo = data[op*13+9] & 0x01;
|
||||
instr->channels[0].ops[op].vibrato = data[op*13+10] & 0x01;
|
||||
instr->channels[0].ops[op].sustaining = data[op*13+5] & 0x01;
|
||||
instr->channels[0].ops[op].ksr = data[op*13+11] & 0x01;
|
||||
instr->channels[0].ops[op].mult = data[op*13+1] & 0x0f;
|
||||
instr->channels[0].ops[op].attack = data[op*13+3] & 0x0f;
|
||||
instr->channels[0].ops[op].decay = data[op*13+6] & 0x0f;
|
||||
instr->channels[0].ops[op].sustain = data[op*13+4] & 0x0f;
|
||||
instr->channels[0].ops[op].release = data[op*13+7] & 0x0f;
|
||||
instr->channels[0].ops[op].waveform = data[26+op] & 0x07;
|
||||
instr->channels[0].ops[op].ksl = data[op*13+0] & 0x03;
|
||||
instr->channels[0].ops[op].level = data[op*13+8] & 0x3f;
|
||||
}
|
||||
instr->channels[0].feedback = data[2] & 0x07;
|
||||
instr->channels[0].am = (data[25] & 0x01) ^ 1;
|
||||
instr->channels[0].offset = 0;
|
||||
instr->channels[0].detune = 0;
|
||||
}
|
||||
|
||||
private static Instrument[] bk_read_bank(byte[] raw, String filename, boolean drum) {
|
||||
uint8_t *data;
|
||||
bank_instr *instr;
|
||||
uint32_t size = bnk_read_mbank(&data, &instr, filename, 28, 256*42+28);
|
||||
if(size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
uint8_t *odata = data;
|
||||
if(memcmp(data+2, "ADLIB-", 6) != 0) {
|
||||
fprintf(stderr, STR_BNK_EMFHDR"\n", filename);
|
||||
free(odata);
|
||||
free(instr);
|
||||
return NULL;
|
||||
}
|
||||
data += 8;
|
||||
for(int i = 0; i < 256; i++) {
|
||||
instr[i].op = b_op0;
|
||||
instr[i].name[0] = 0;
|
||||
}
|
||||
// uint16_t nnorm = data[0];
|
||||
uint32_t ninst = dmx_read_uint16(&data[2]);
|
||||
data += 20;
|
||||
if((ninst*42+28) > size) {
|
||||
fprintf(stderr, STR_BNK_EEOD"\n", filename);
|
||||
free(odata);
|
||||
free(instr);
|
||||
return NULL;
|
||||
}
|
||||
data += ninst*12;
|
||||
int pos = 0;
|
||||
for(int i = 0; i < ninst; i++, data += 30) {
|
||||
if(data[0] != 0) {
|
||||
continue;
|
||||
}
|
||||
bk_read_instr(&instr[pos + (drum ? 128 : 0)], data+2, drum);
|
||||
uint8_t *ndata = odata+(i*12+28);
|
||||
instr[pos + (drum ? 128 : 0)].percnum = ndata[2] & 0x7f;
|
||||
memcpy(instr[pos + (drum ? 128 : 0)].name, ndata+3, 8);
|
||||
instr[pos + (drum ? 128 : 0)].name[8] = 0;
|
||||
if(++pos == 128) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(odata);
|
||||
return instr;
|
||||
}
|
||||
*/
|
||||
|
||||
private static Instrument[] bnk_read_bank(byte[] raw, String name, boolean drum) {
|
||||
int dot = name.lastIndexOf('.');
|
||||
if(dot < 0 || dot == name.length() - 1) {
|
||||
Log.SOUND.error("Bank-Datei '%s' hat keine Erweiterung", name);
|
||||
return null;
|
||||
}
|
||||
String ext = name.substring(dot + 1);
|
||||
if(ext.equalsIgnoreCase("dmx") || ext.equalsIgnoreCase("op2") || ext.equalsIgnoreCase("lmp")) {
|
||||
return dmx_read_bank(raw, name);
|
||||
}
|
||||
else if(ext.equalsIgnoreCase("tmb")) {
|
||||
return tmb_read_bank(raw, name);
|
||||
}
|
||||
// else if(ext.equalsIgnoreCase("sb")) {
|
||||
// return sb_read_bank(raw, name, drum);
|
||||
// }
|
||||
// else if(ext.equalsIgnoreCase("o3")) {
|
||||
// return sb3_read_bank(raw, name, drum);
|
||||
// }
|
||||
// else if(ext.equalsIgnoreCase("op3")) {
|
||||
// return op3_read_bank(raw, name);
|
||||
// }
|
||||
// else if(ext.equalsIgnoreCase("ad") || ext.equalsIgnoreCase("opl")) {
|
||||
// return ad_read_bank(raw, name);
|
||||
// }
|
||||
// else if(ext.equalsIgnoreCase("bnk")) {
|
||||
// return bk_read_bank(raw, name, drum);
|
||||
// }
|
||||
Log.SOUND.error("Format von Bank-Datei '%s' unbekannt", name);
|
||||
return null;
|
||||
// else if(strcmp(ext, "skb") == 0) {
|
||||
// return skb_read_bank(filename);
|
||||
// }
|
||||
// else if(strcmp(ext, "ibk") == 0) {
|
||||
// return ibk_read_bank(filename, drum);
|
||||
// }
|
||||
// else if((strcmp(ext, "tim") == 0) || (strcmp(ext, "snd") == 0)) {
|
||||
// return tim_read_bank(filename, drum);
|
||||
// }
|
||||
// else if(strcmp(ext, "wopl") == 0) {
|
||||
// return wopl_read_bank(filename);
|
||||
// }
|
||||
}
|
||||
|
||||
private static Instrument[] readBank(File file, boolean drum) {
|
||||
byte[] raw;
|
||||
try {
|
||||
raw = Files.readAllBytes(file.toPath());
|
||||
}
|
||||
catch(FileNotFoundException e) {
|
||||
Log.SOUND.error("Fehler beim Lesen von Bank-Datei '%s': Datei nicht gefunden", file);
|
||||
return null;
|
||||
}
|
||||
catch(IOException e) {
|
||||
Log.SOUND.error(e, "Fehler beim Lesen von Bank-Datei '%s'", file);
|
||||
return null;
|
||||
}
|
||||
return bnk_read_bank(raw, file.getAbsolutePath(), drum);
|
||||
}
|
||||
|
||||
private static Instrument[] readBank(String path, boolean drum) {
|
||||
byte[] raw;
|
||||
try {
|
||||
raw = FileUtils.readBytes(path);
|
||||
}
|
||||
catch(FileNotFoundException e) {
|
||||
Log.SOUND.error("Fehler beim Lesen von Bank-Datei '%s': Datei nicht gefunden", path);
|
||||
return null;
|
||||
}
|
||||
catch(IOException e) {
|
||||
Log.SOUND.error(e, "Fehler beim Lesen von Bank-Datei '%s'", path);
|
||||
return null;
|
||||
}
|
||||
return bnk_read_bank(raw, path, drum);
|
||||
}
|
||||
|
||||
public static Instrument[] readBank(String filename, String drumname, boolean usedrum) {
|
||||
Instrument[] ins1 = readBank(filename, usedrum);
|
||||
if(ins1 != null && drumname != null) {
|
||||
Instrument[] ins2 = readBank(drumname, !usedrum);
|
||||
if(ins2 == null)
|
||||
return null;
|
||||
System.arraycopy(ins2, 128, ins1, 128, 128);
|
||||
}
|
||||
return ins1;
|
||||
}
|
||||
|
||||
/*
|
||||
uint32_t skb_write_instr(bank_instr *instr, uint8_t *data, uint32_t pos) {
|
||||
data += pos;
|
||||
uint8_t nlen = strlen(instr->name);
|
||||
data[0] = (instr->op << 6) | nlen;
|
||||
memcpy(data+1, instr->name, nlen);
|
||||
pos += 1 + nlen;
|
||||
if(instr->op == b_op0) {
|
||||
return pos;
|
||||
}
|
||||
int numch = (instr->op == b_op2) ? 1 : 2;
|
||||
data += 1 + nlen;
|
||||
data[0] = (instr->fixed << 7) | instr->percnum;
|
||||
data[1] = ((numch == 2) ? ((instr->channels[1].am << 7) | (instr->channels[1].feedback << 4)) : 0) | (instr->channels[0].am << 3) | instr->channels[0].feedback;
|
||||
data += 2;
|
||||
for(int ch = 0; ch < numch; ch++) {
|
||||
data[0] = (uint8_t)((int16_t)(instr->channels[ch].detune + 128));
|
||||
data[1] = (uint8_t)((int16_t)(instr->channels[ch].offset + 128));
|
||||
data += 2;
|
||||
for(int op = 0; op < 2; op++) {
|
||||
data[0] = (instr->channels[ch].ops[op].tremolo << 7) | (instr->channels[ch].ops[op].vibrato << 6) | (instr->channels[ch].ops[op].sustaining << 5) |
|
||||
(instr->channels[ch].ops[op].ksr << 4) | instr->channels[ch].ops[op].mult;
|
||||
data[1] = (instr->channels[ch].ops[op].ksl << 6) | instr->channels[ch].ops[op].level;
|
||||
data[2] = (instr->channels[ch].ops[op].attack << 4) | instr->channels[ch].ops[op].decay;
|
||||
data[3] = (instr->channels[ch].ops[op].sustain << 4) | instr->channels[ch].ops[op].release;
|
||||
data += 4;
|
||||
}
|
||||
data[0] = (instr->channels[ch].ops[0].waveform << 4) | instr->channels[ch].ops[1].waveform;
|
||||
data += 1;
|
||||
}
|
||||
return pos + 2 + (11 * numch);
|
||||
}
|
||||
|
||||
bool skb_write_bank(bank_instr *instr, const char *filename) {
|
||||
int err;
|
||||
FILE *fd = fopen(filename, "wb");
|
||||
if(fd == NULL) {
|
||||
err = errno;
|
||||
fprintf(stderr, STR_BNK_OPNERR"\n", filename, strerror(err), err);
|
||||
return false;
|
||||
}
|
||||
if(fwrite("SKB!", 1, 4, fd) != 4) {
|
||||
fprintf(stderr, STR_BNK_EWIO"\n", filename);
|
||||
fclose(fd);
|
||||
return false;
|
||||
}
|
||||
uint8_t *data = malloc(256*56);
|
||||
uint32_t size = 0;
|
||||
for(int i = 0; i < 256; i++) {
|
||||
size = skb_write_instr(&instr[i], data, size);
|
||||
}
|
||||
if(fwrite(data, 1, size, fd) != size) {
|
||||
fprintf(stderr, STR_BNK_EWIO"\n", filename);
|
||||
fclose(fd);
|
||||
free(data);
|
||||
return false;
|
||||
}
|
||||
fclose(fd);
|
||||
free(data);
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
void ibk_read_instr(bank_instr *instr, uint8_t *data, uint8_t drum) {
|
||||
instr->fixed = drum;
|
||||
instr->op = b_op2;
|
||||
|
@ -263,318 +717,9 @@ typedef struct {
|
|||
free(odata);
|
||||
return instr;
|
||||
}
|
||||
*/
|
||||
|
||||
void sb_read_instr(bank_instr *instr, uint8_t *data, uint8_t drum) {
|
||||
for(int h = 0; h < 28; h++) {
|
||||
instr->name[h] = (data[h] == 0x1a) ? ' ' : data[h];
|
||||
}
|
||||
instr->name[28] = 0;
|
||||
instr->percnum = data[35] & 0x7f;
|
||||
instr->fixed = drum;
|
||||
instr->op = b_op2;
|
||||
data += 36;
|
||||
for(int op = 0; op < 2; op++) {
|
||||
instr->channels[0].ops[op].tremolo = (data[op+0] & 0x80) > 0;
|
||||
instr->channels[0].ops[op].vibrato = (data[op+0] & 0x40) > 0;
|
||||
instr->channels[0].ops[op].sustaining = (data[op+0] & 0x20) > 0;
|
||||
instr->channels[0].ops[op].ksr = (data[op+0] & 0x10) > 0;
|
||||
instr->channels[0].ops[op].mult = data[op+0] & 0x0f;
|
||||
instr->channels[0].ops[op].attack = (data[op+4] >> 4) & 0x0f;
|
||||
instr->channels[0].ops[op].decay = data[op+4] & 0x0f;
|
||||
instr->channels[0].ops[op].sustain = (data[op+6] >> 4) & 0x0f;
|
||||
instr->channels[0].ops[op].release = data[op+6] & 0x0f;
|
||||
instr->channels[0].ops[op].waveform = data[op+8] & 0x07;
|
||||
instr->channels[0].ops[op].ksl = (data[op+2] >> 6) & 0x03;
|
||||
instr->channels[0].ops[op].level = data[op+2] & 0x3f;
|
||||
}
|
||||
instr->channels[0].feedback = (data[10] >> 1) & 0x07;
|
||||
instr->channels[0].am = data[10] & 0x01;
|
||||
instr->channels[0].offset = 0;
|
||||
instr->channels[0].detune = 0;
|
||||
}
|
||||
|
||||
bank_instr *sb_read_bank(const char *filename, uint8_t drum) {
|
||||
uint8_t *data;
|
||||
bank_instr *instr;
|
||||
uint32_t size = bnk_read_sbank(&data, &instr, filename, 128*52);
|
||||
if(size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
uint8_t *odata = data;
|
||||
for(int i = 0; i < 128; i++) {
|
||||
instr[i + (drum ? 0 : 128)].op = b_op0;
|
||||
instr[i + (drum ? 0 : 128)].name[0] = 0;
|
||||
}
|
||||
for(int i = 0; i < 128; i++) {
|
||||
sb_read_instr(&instr[i + (drum ? 128 : 0)], data, drum);
|
||||
data += 52;
|
||||
}
|
||||
free(odata);
|
||||
return instr;
|
||||
}
|
||||
|
||||
void sb3_read_instr(bank_instr *instr, uint8_t *data, uint8_t drum) {
|
||||
for(int h = 0; h < 28; h++) {
|
||||
instr->name[h] = (data[h] == 0x1a) ? ' ' : data[h];
|
||||
}
|
||||
instr->name[28] = 0;
|
||||
instr->percnum = data[35] & 0x7f;
|
||||
instr->fixed = drum;
|
||||
instr->op = (data[0] == '4') ? b_op4 : b_op2;
|
||||
data += 36;
|
||||
for(int ch = 0; ch < 2; ch++) {
|
||||
for(int op = 0; op < 2; op++) {
|
||||
instr->channels[ch].ops[op].tremolo = (data[op+0] & 0x80) > 0;
|
||||
instr->channels[ch].ops[op].vibrato = (data[op+0] & 0x40) > 0;
|
||||
instr->channels[ch].ops[op].sustaining = (data[op+0] & 0x20) > 0;
|
||||
instr->channels[ch].ops[op].ksr = (data[op+0] & 0x10) > 0;
|
||||
instr->channels[ch].ops[op].mult = data[op+0] & 0x0f;
|
||||
instr->channels[ch].ops[op].attack = (data[op+4] >> 4) & 0x0f;
|
||||
instr->channels[ch].ops[op].decay = data[op+4] & 0x0f;
|
||||
instr->channels[ch].ops[op].sustain = (data[op+6] >> 4) & 0x0f;
|
||||
instr->channels[ch].ops[op].release = data[op+6] & 0x0f;
|
||||
instr->channels[ch].ops[op].waveform = data[op+8] & 0x07;
|
||||
instr->channels[ch].ops[op].ksl = (data[op+2] >> 6) & 0x03;
|
||||
instr->channels[ch].ops[op].level = data[op+2] & 0x3f;
|
||||
}
|
||||
instr->channels[ch].feedback = (data[10] >> 1) & 0x07;
|
||||
instr->channels[ch].am = data[10] & 0x01;
|
||||
instr->channels[ch].offset = 0;
|
||||
instr->channels[ch].detune = 0;
|
||||
data += 11;
|
||||
}
|
||||
}
|
||||
|
||||
bank_instr *sb3_read_bank(const char *filename, uint8_t drum) {
|
||||
uint8_t *data;
|
||||
bank_instr *instr;
|
||||
uint32_t size = bnk_read_sbank(&data, &instr, filename, 128*60);
|
||||
if(size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
uint8_t *odata = data;
|
||||
for(int i = 0; i < 128; i++) {
|
||||
instr[i + (drum ? 0 : 128)].op = b_op0;
|
||||
instr[i + (drum ? 0 : 128)].name[0] = 0;
|
||||
}
|
||||
for(int i = 0; i < 128; i++) {
|
||||
sb3_read_instr(&instr[i + (drum ? 128 : 0)], data, drum);
|
||||
data += 60;
|
||||
}
|
||||
free(odata);
|
||||
return instr;
|
||||
}
|
||||
|
||||
void op3_read_instr(bank_instr *instr, uint8_t *data, uint8_t drum) {
|
||||
instr->percnum = data[1] & 0x7f;
|
||||
instr->fixed = drum;
|
||||
instr->op = ((data[0] & 0x01) > 0) ? b_op4 : b_op2;
|
||||
data += 2;
|
||||
for(int ch = 0; ch < 2; ch++) {
|
||||
for(int op = 0; op < 2; op++) {
|
||||
instr->channels[ch].ops[op].tremolo = (data[op*6+0] & 0x80) > 0;
|
||||
instr->channels[ch].ops[op].vibrato = (data[op*6+0] & 0x40) > 0;
|
||||
instr->channels[ch].ops[op].sustaining = (data[op*6+0] & 0x20) > 0;
|
||||
instr->channels[ch].ops[op].ksr = (data[op*6+0] & 0x10) > 0;
|
||||
instr->channels[ch].ops[op].mult = data[op*6+0] & 0x0f;
|
||||
instr->channels[ch].ops[op].attack = (data[op*6+2] >> 4) & 0x0f;
|
||||
instr->channels[ch].ops[op].decay = data[op*6+2] & 0x0f;
|
||||
instr->channels[ch].ops[op].sustain = (data[op*6+3] >> 4) & 0x0f;
|
||||
instr->channels[ch].ops[op].release = data[op*6+3] & 0x0f;
|
||||
instr->channels[ch].ops[op].waveform = data[op*6+4] & 0x07;
|
||||
instr->channels[ch].ops[op].ksl = (data[op*6+1] >> 6) & 0x03;
|
||||
instr->channels[ch].ops[op].level = data[op*6+1] & 0x3f;
|
||||
}
|
||||
instr->channels[ch].feedback = (data[5] >> 1) & 0x07;
|
||||
instr->channels[ch].am = data[5] & 0x01;
|
||||
instr->channels[ch].offset = 0;
|
||||
instr->channels[ch].detune = 0;
|
||||
data += 11;
|
||||
}
|
||||
}
|
||||
|
||||
bank_instr *op3_read_bank(const char *filename) {
|
||||
uint8_t *data;
|
||||
bank_instr *instr;
|
||||
uint32_t size = bnk_read_mhbank(&data, &instr, filename, 16, 256*24+16, "Junglevision Patch File\x1a", 24);
|
||||
if(size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
uint8_t *odata = data;
|
||||
for(int i = 0; i < 256; i++) {
|
||||
instr[i].op = b_op0;
|
||||
instr[i].name[0] = 0;
|
||||
}
|
||||
data += 8;
|
||||
uint16_t nmelo = dmx_read_uint16(&data[0]);
|
||||
uint16_t ndrum = dmx_read_uint16(&data[2]);
|
||||
uint16_t omelo = dmx_read_uint16(&data[4]);
|
||||
uint16_t odrum = dmx_read_uint16(&data[6]);
|
||||
data += 8;
|
||||
if((((nmelo+ndrum)*24+16) > size) || ((omelo+nmelo) > 128) || ((odrum+ndrum) > 128)) {
|
||||
fprintf(stderr, STR_BNK_EEOD"\n", filename);
|
||||
free(odata);
|
||||
free(instr);
|
||||
return NULL;
|
||||
}
|
||||
for(int i = 0; i < nmelo; i++) {
|
||||
op3_read_instr(&instr[i + omelo], data, 0);
|
||||
data += 24;
|
||||
}
|
||||
for(int i = 0; i < ndrum; i++) {
|
||||
op3_read_instr(&instr[i + odrum + 128], data, 1);
|
||||
data += 24;
|
||||
}
|
||||
free(odata);
|
||||
return instr;
|
||||
}
|
||||
|
||||
void ad_read_instr(bank_instr *instr, uint8_t *data, uint8_t drum, uint16_t isize) {
|
||||
if(isize < 12) {
|
||||
return;
|
||||
}
|
||||
instr->percnum = data[0] & 0x7f;
|
||||
instr->fixed = drum;
|
||||
instr->op = (isize >= 23) ? b_op4 : b_op2;
|
||||
data += 1;
|
||||
instr->channels[0].feedback = instr->channels[1].feedback = (data[5] >> 1) & 0x07;
|
||||
instr->channels[0].am = data[5] & 0x01;
|
||||
instr->channels[1].am = (data[5] & 0x80) > 0;
|
||||
for(int ch = 0; ch < ((isize >= 23) ? 2 : 1); ch++) {
|
||||
for(int op = 0; op < 2; op++) {
|
||||
instr->channels[ch].ops[op].tremolo = (data[op*6+0] & 0x80) > 0;
|
||||
instr->channels[ch].ops[op].vibrato = (data[op*6+0] & 0x40) > 0;
|
||||
instr->channels[ch].ops[op].sustaining = (data[op*6+0] & 0x20) > 0;
|
||||
instr->channels[ch].ops[op].ksr = (data[op*6+0] & 0x10) > 0;
|
||||
instr->channels[ch].ops[op].mult = data[op*6+0] & 0x0f;
|
||||
instr->channels[ch].ops[op].attack = (data[op*6+2] >> 4) & 0x0f;
|
||||
instr->channels[ch].ops[op].decay = data[op*6+2] & 0x0f;
|
||||
instr->channels[ch].ops[op].sustain = (data[op*6+3] >> 4) & 0x0f;
|
||||
instr->channels[ch].ops[op].release = data[op*6+3] & 0x0f;
|
||||
instr->channels[ch].ops[op].waveform = data[op*6+4] & 0x07;
|
||||
instr->channels[ch].ops[op].ksl = (data[op*6+1] >> 6) & 0x03;
|
||||
instr->channels[ch].ops[op].level = data[op*6+1] & 0x3f;
|
||||
}
|
||||
instr->channels[ch].offset = 0;
|
||||
instr->channels[ch].detune = 0;
|
||||
data += 11;
|
||||
}
|
||||
}
|
||||
|
||||
bank_instr *ad_read_bank(const char *filename) {
|
||||
uint8_t *data;
|
||||
bank_instr *instr;
|
||||
uint32_t size = bnk_read_mbank(&data, &instr, filename, 2, 256*20+2);
|
||||
if(size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
uint8_t *odata = data;
|
||||
for(int i = 0; i < 256; i++) {
|
||||
instr[i].op = b_op0;
|
||||
instr[i].name[0] = 0;
|
||||
}
|
||||
for(int i = 0;; i++, data += 6) {
|
||||
if((i*6) >= size) {
|
||||
fprintf(stderr, STR_BNK_EEOD"\n", filename);
|
||||
free(odata);
|
||||
free(instr);
|
||||
return NULL;
|
||||
}
|
||||
uint8_t prog = data[0];
|
||||
if(prog == 0xff) {
|
||||
break;
|
||||
}
|
||||
if(prog >= 128) {
|
||||
continue;
|
||||
}
|
||||
uint8_t bank = data[1];
|
||||
if((bank != 0) && (bank != 127)) {
|
||||
continue;
|
||||
}
|
||||
uint16_t offs = dmx_read_uint16(data+2);
|
||||
uint16_t isize;
|
||||
if(((offs+2) > size) || ((offs+(isize = dmx_read_uint16(odata+offs))) > size) || (isize < 2)) {
|
||||
fprintf(stderr, STR_BNK_EEOD"\n", filename);
|
||||
free(odata);
|
||||
free(instr);
|
||||
return NULL;
|
||||
}
|
||||
ad_read_instr(&instr[prog + ((bank == 127) ? 128 : 0)], odata+(offs+2), bank == 127, isize-2);
|
||||
}
|
||||
free(odata);
|
||||
return instr;
|
||||
}
|
||||
|
||||
void bk_read_instr(bank_instr *instr, uint8_t *data, uint8_t drum) {
|
||||
instr->fixed = drum;
|
||||
instr->op = b_op2;
|
||||
for(int op = 0; op < 2; op++) {
|
||||
instr->channels[0].ops[op].tremolo = data[op*13+9] & 0x01;
|
||||
instr->channels[0].ops[op].vibrato = data[op*13+10] & 0x01;
|
||||
instr->channels[0].ops[op].sustaining = data[op*13+5] & 0x01;
|
||||
instr->channels[0].ops[op].ksr = data[op*13+11] & 0x01;
|
||||
instr->channels[0].ops[op].mult = data[op*13+1] & 0x0f;
|
||||
instr->channels[0].ops[op].attack = data[op*13+3] & 0x0f;
|
||||
instr->channels[0].ops[op].decay = data[op*13+6] & 0x0f;
|
||||
instr->channels[0].ops[op].sustain = data[op*13+4] & 0x0f;
|
||||
instr->channels[0].ops[op].release = data[op*13+7] & 0x0f;
|
||||
instr->channels[0].ops[op].waveform = data[26+op] & 0x07;
|
||||
instr->channels[0].ops[op].ksl = data[op*13+0] & 0x03;
|
||||
instr->channels[0].ops[op].level = data[op*13+8] & 0x3f;
|
||||
}
|
||||
instr->channels[0].feedback = data[2] & 0x07;
|
||||
instr->channels[0].am = (data[25] & 0x01) ^ 1;
|
||||
instr->channels[0].offset = 0;
|
||||
instr->channels[0].detune = 0;
|
||||
}
|
||||
|
||||
bank_instr *bk_read_bank(const char *filename, uint8_t drum) {
|
||||
uint8_t *data;
|
||||
bank_instr *instr;
|
||||
uint32_t size = bnk_read_mbank(&data, &instr, filename, 28, 256*42+28);
|
||||
if(size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
uint8_t *odata = data;
|
||||
if(memcmp(data+2, "ADLIB-", 6) != 0) {
|
||||
fprintf(stderr, STR_BNK_EMFHDR"\n", filename);
|
||||
free(odata);
|
||||
free(instr);
|
||||
return NULL;
|
||||
}
|
||||
data += 8;
|
||||
for(int i = 0; i < 256; i++) {
|
||||
instr[i].op = b_op0;
|
||||
instr[i].name[0] = 0;
|
||||
}
|
||||
// uint16_t nnorm = data[0];
|
||||
uint32_t ninst = dmx_read_uint16(&data[2]);
|
||||
data += 20;
|
||||
if((ninst*42+28) > size) {
|
||||
fprintf(stderr, STR_BNK_EEOD"\n", filename);
|
||||
free(odata);
|
||||
free(instr);
|
||||
return NULL;
|
||||
}
|
||||
data += ninst*12;
|
||||
int pos = 0;
|
||||
for(int i = 0; i < ninst; i++, data += 30) {
|
||||
if(data[0] != 0) {
|
||||
continue;
|
||||
}
|
||||
bk_read_instr(&instr[pos + (drum ? 128 : 0)], data+2, drum);
|
||||
uint8_t *ndata = odata+(i*12+28);
|
||||
instr[pos + (drum ? 128 : 0)].percnum = ndata[2] & 0x7f;
|
||||
memcpy(instr[pos + (drum ? 128 : 0)].name, ndata+3, 8);
|
||||
instr[pos + (drum ? 128 : 0)].name[8] = 0;
|
||||
if(++pos == 128) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(odata);
|
||||
return instr;
|
||||
}
|
||||
|
||||
/*
|
||||
void tim_read_instr(bank_instr *instr, uint8_t *data) {
|
||||
instr->percnum = 0;
|
||||
instr->fixed = 0;
|
||||
|
@ -780,155 +925,4 @@ typedef struct {
|
|||
return instr;
|
||||
}
|
||||
*/
|
||||
|
||||
private static Instrument[] bnk_read_bank(byte[] raw, String name, boolean drum) {
|
||||
int dot = name.lastIndexOf('.');
|
||||
if(dot < 0 || dot == name.length() - 1) {
|
||||
Log.SOUND.error("Bank-Datei '%s' hat keine Erweiterung", name);
|
||||
return null;
|
||||
}
|
||||
String ext = name.substring(dot + 1);
|
||||
// if(strcmp(ext, "skb") == 0) {
|
||||
// return skb_read_bank(filename);
|
||||
// }
|
||||
// else
|
||||
if(ext.equalsIgnoreCase("dmx") || ext.equalsIgnoreCase("op2") || ext.equalsIgnoreCase("lmp")) {
|
||||
return dmx_read_bank(raw, name);
|
||||
}
|
||||
// else if(strcmp(ext, "tmb") == 0) {
|
||||
// return tmb_read_bank(filename);
|
||||
// }
|
||||
// else if(strcmp(ext, "ibk") == 0) {
|
||||
// return ibk_read_bank(filename, drum);
|
||||
// }
|
||||
// else if(strcmp(ext, "sb") == 0) {
|
||||
// return sb_read_bank(filename, drum);
|
||||
// }
|
||||
// else if(strcmp(ext, "o3") == 0) {
|
||||
// return sb3_read_bank(filename, drum);
|
||||
// }
|
||||
// else if(strcmp(ext, "op3") == 0) {
|
||||
// return op3_read_bank(filename);
|
||||
// }
|
||||
// else if((strcmp(ext, "ad") == 0) || (strcmp(ext, "opl") == 0)) {
|
||||
// return ad_read_bank(filename);
|
||||
// }
|
||||
// else if(strcmp(ext, "bnk") == 0) {
|
||||
// return bk_read_bank(filename, drum);
|
||||
// }
|
||||
// else if((strcmp(ext, "tim") == 0) || (strcmp(ext, "snd") == 0)) {
|
||||
// return tim_read_bank(filename, drum);
|
||||
// }
|
||||
// else if(strcmp(ext, "wopl") == 0) {
|
||||
// return wopl_read_bank(filename);
|
||||
// }
|
||||
Log.SOUND.error("Format von Bank-Datei '%s' unbekannt", name);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Instrument[] readBank(File file, boolean drum) {
|
||||
byte[] raw;
|
||||
try {
|
||||
raw = Files.readAllBytes(file.toPath());
|
||||
}
|
||||
catch(FileNotFoundException e) {
|
||||
Log.SOUND.error("Fehler beim Lesen von Bank-Datei '%s': Datei nicht gefunden", file);
|
||||
return null;
|
||||
}
|
||||
catch(IOException e) {
|
||||
Log.SOUND.error(e, "Fehler beim Lesen von Bank-Datei '%s'", file);
|
||||
return null;
|
||||
}
|
||||
return bnk_read_bank(raw, file.getAbsolutePath(), drum);
|
||||
}
|
||||
|
||||
private static Instrument[] readBank(String path, boolean drum) {
|
||||
byte[] raw;
|
||||
try {
|
||||
raw = FileUtils.readBytes(path);
|
||||
}
|
||||
catch(FileNotFoundException e) {
|
||||
Log.SOUND.error("Fehler beim Lesen von Bank-Datei '%s': Datei nicht gefunden", path);
|
||||
return null;
|
||||
}
|
||||
catch(IOException e) {
|
||||
Log.SOUND.error(e, "Fehler beim Lesen von Bank-Datei '%s'", path);
|
||||
return null;
|
||||
}
|
||||
return bnk_read_bank(raw, path, drum);
|
||||
}
|
||||
|
||||
public static Instrument[] readBank(String filename, String drumname, boolean usedrum) {
|
||||
Instrument[] ins1 = readBank(filename, usedrum);
|
||||
if(ins1 != null && drumname != null) {
|
||||
Instrument[] ins2 = readBank(drumname, !usedrum);
|
||||
if(ins2 == null)
|
||||
return null;
|
||||
System.arraycopy(ins2, 128, ins1, 128, 128);
|
||||
}
|
||||
return ins1;
|
||||
}
|
||||
|
||||
/*
|
||||
uint32_t skb_write_instr(bank_instr *instr, uint8_t *data, uint32_t pos) {
|
||||
data += pos;
|
||||
uint8_t nlen = strlen(instr->name);
|
||||
data[0] = (instr->op << 6) | nlen;
|
||||
memcpy(data+1, instr->name, nlen);
|
||||
pos += 1 + nlen;
|
||||
if(instr->op == b_op0) {
|
||||
return pos;
|
||||
}
|
||||
int numch = (instr->op == b_op2) ? 1 : 2;
|
||||
data += 1 + nlen;
|
||||
data[0] = (instr->fixed << 7) | instr->percnum;
|
||||
data[1] = ((numch == 2) ? ((instr->channels[1].am << 7) | (instr->channels[1].feedback << 4)) : 0) | (instr->channels[0].am << 3) | instr->channels[0].feedback;
|
||||
data += 2;
|
||||
for(int ch = 0; ch < numch; ch++) {
|
||||
data[0] = (uint8_t)((int16_t)(instr->channels[ch].detune + 128));
|
||||
data[1] = (uint8_t)((int16_t)(instr->channels[ch].offset + 128));
|
||||
data += 2;
|
||||
for(int op = 0; op < 2; op++) {
|
||||
data[0] = (instr->channels[ch].ops[op].tremolo << 7) | (instr->channels[ch].ops[op].vibrato << 6) | (instr->channels[ch].ops[op].sustaining << 5) |
|
||||
(instr->channels[ch].ops[op].ksr << 4) | instr->channels[ch].ops[op].mult;
|
||||
data[1] = (instr->channels[ch].ops[op].ksl << 6) | instr->channels[ch].ops[op].level;
|
||||
data[2] = (instr->channels[ch].ops[op].attack << 4) | instr->channels[ch].ops[op].decay;
|
||||
data[3] = (instr->channels[ch].ops[op].sustain << 4) | instr->channels[ch].ops[op].release;
|
||||
data += 4;
|
||||
}
|
||||
data[0] = (instr->channels[ch].ops[0].waveform << 4) | instr->channels[ch].ops[1].waveform;
|
||||
data += 1;
|
||||
}
|
||||
return pos + 2 + (11 * numch);
|
||||
}
|
||||
|
||||
bool skb_write_bank(bank_instr *instr, const char *filename) {
|
||||
int err;
|
||||
FILE *fd = fopen(filename, "wb");
|
||||
if(fd == NULL) {
|
||||
err = errno;
|
||||
fprintf(stderr, STR_BNK_OPNERR"\n", filename, strerror(err), err);
|
||||
return false;
|
||||
}
|
||||
if(fwrite("SKB!", 1, 4, fd) != 4) {
|
||||
fprintf(stderr, STR_BNK_EWIO"\n", filename);
|
||||
fclose(fd);
|
||||
return false;
|
||||
}
|
||||
uint8_t *data = malloc(256*56);
|
||||
uint32_t size = 0;
|
||||
for(int i = 0; i < 256; i++) {
|
||||
size = skb_write_instr(&instr[i], data, size);
|
||||
}
|
||||
if(fwrite(data, 1, size, fd) != size) {
|
||||
fprintf(stderr, STR_BNK_EWIO"\n", filename);
|
||||
fclose(fd);
|
||||
free(data);
|
||||
return false;
|
||||
}
|
||||
fclose(fd);
|
||||
free(data);
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -2,56 +2,56 @@ package client.audio;
|
|||
|
||||
public class WavWriter {
|
||||
/*
|
||||
static const char *wav_hdr = "RIFF";
|
||||
static const char *wav_hdr_fmt = "fmt ";
|
||||
static const char *wav_hdr_data = "data";
|
||||
static const char *wav_format = "WAVE";
|
||||
#define WAV_HDRSIZE 44
|
||||
private static final byte[] wav_hdr = "RIFF".getBytes();
|
||||
private static final byte[] wav_hdr_fmt = "fmt ".getBytes();
|
||||
private static final byte[] wav_hdr_data = "data".getBytes();
|
||||
private static final byte[] wav_format = "WAVE".getBytes();
|
||||
private static final int WAV_HDRSIZE = 44;
|
||||
|
||||
#define STR_WAV_OPNERR "Fehler beim Oeffnen von WAV-Datei '%s': %s (%d)"
|
||||
#define STR_WAV_WRITERR "Fehler beim Schreiben nach WAV-Datei '%s': "
|
||||
#define STR_WAV_EIO STR_WAV_WRITERR "E/A-Fehler"
|
||||
#define STR_WAV_EGEN STR_WAV_WRITERR "%s (%d)"
|
||||
|
||||
typedef struct {
|
||||
uint32_t samplerate;
|
||||
uint16_t channels;
|
||||
uint16_t bytes;
|
||||
uint32_t samples;
|
||||
FILE *fd;
|
||||
const char *filename;
|
||||
uint8_t *buffer;
|
||||
} wav_handle;
|
||||
private final int samplerate;
|
||||
private final int channels;
|
||||
private final OutputStream fd;
|
||||
private final File filename;
|
||||
private final byte[] buffer;
|
||||
|
||||
void wav_write_uint32(uint8_t *data, uint32_t value) {
|
||||
private int samples;
|
||||
|
||||
private void wav_write_uint32(byte[] data, int offset, int value) {
|
||||
for(int h = 0; h < 4; h++) {
|
||||
data[h] = ((uint32_t)((value >> (8*h) & 0xff)));
|
||||
}
|
||||
}
|
||||
|
||||
void wav_write_uint16(uint8_t *data, uint16_t value) {
|
||||
private void wav_write_uint16(byte[] data, int offset, short value) {
|
||||
for(int h = 0; h < 2; h++) {
|
||||
data[h] = ((uint16_t)((value >> (8*h) & 0xff)));
|
||||
}
|
||||
}
|
||||
|
||||
void wav_write_header(uint8_t *data, uint32_t samplerate, uint16_t channels, uint32_t samples, uint16_t bytes) {
|
||||
private static byte[] makeHeader(int samplerate, int channels, int samples, int bytes) {
|
||||
byte[] data = new byte[WAV_HDRSIZE];
|
||||
memcpy(data+0, wav_hdr, 4);
|
||||
wav_write_uint32(data+4, 36 + samples * ((uint32_t)channels) * ((uint32_t)bytes));
|
||||
wav_write_uint32(data+4, 36 + samples * channels * bytes);
|
||||
memcpy(data+8, wav_format, 4);
|
||||
memcpy(data+12, wav_hdr_fmt, 4);
|
||||
wav_write_uint32(data+16, 16);
|
||||
wav_write_uint16(data+20, 1);
|
||||
wav_write_uint16(data+22, channels);
|
||||
wav_write_uint32(data+24, samplerate);
|
||||
wav_write_uint32(data+28, samplerate * ((uint32_t)channels) * ((uint32_t)bytes));
|
||||
wav_write_uint32(data+28, samplerate * channels * bytes);
|
||||
wav_write_uint16(data+32, channels * bytes);
|
||||
wav_write_uint16(data+34, 8 * bytes);
|
||||
memcpy(data+36, wav_hdr_data, 4);
|
||||
wav_write_uint32(data+40, samples * ((uint32_t)channels) * ((uint32_t)bytes));
|
||||
wav_write_uint32(data+40, samples * channels * bytes);
|
||||
return data;
|
||||
}
|
||||
|
||||
bool wav_open(wav_handle *wav, const char *filename, uint32_t samplerate, uint16_t channels, uint16_t bytes) {
|
||||
public WavWriter(File filename, int samplerate, int channels) throws IOException {
|
||||
int err;
|
||||
FILE *fd = fopen(filename, "wb");
|
||||
if(fd == NULL) {
|
||||
|
@ -69,13 +69,10 @@ public class WavWriter {
|
|||
wav->fd = fd;
|
||||
wav->samplerate = samplerate;
|
||||
wav->channels = channels;
|
||||
wav->bytes = bytes;
|
||||
wav->samples = 0;
|
||||
wav->filename = filename;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wav_close(wav_handle *wav) {
|
||||
public boolean close() {
|
||||
if(wav->fd == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
@ -87,7 +84,7 @@ public class WavWriter {
|
|||
return false;
|
||||
}
|
||||
uint8_t header[WAV_HDRSIZE];
|
||||
wav_write_header(header, wav->samplerate, wav->channels, wav->samples, wav->bytes);
|
||||
wav_write_header(header, wav->samplerate, wav->channels, wav->samples, 2);
|
||||
if(fwrite(header, 1, WAV_HDRSIZE, wav->fd) != WAV_HDRSIZE) {
|
||||
mid_log(STR_WAV_EIO, wav->filename);
|
||||
fclose(wav->fd);
|
||||
|
@ -96,5 +93,21 @@ public class WavWriter {
|
|||
fclose(wav->fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void write(short[] samples, int offset, int count) {
|
||||
if(wav->fd == NULL) {
|
||||
return;
|
||||
}
|
||||
for(int c = 0; c < (count * ((uint32_t)wav->channels)); c++) {
|
||||
wav_write_uint16((wav->buffer)+(c*SND_SMPSIZE), samples[c]);
|
||||
}
|
||||
if(fwrite(wav->buffer, 1, SND_SMPSIZE * ((uint32_t)wav->channels) * count, wav->fd) != (SND_SMPSIZE * ((uint32_t)wav->channels) * count)) {
|
||||
fprintf(stderr, STR_WAV_EIO"\n", wav->filename);
|
||||
fclose(wav->fd);
|
||||
wav->fd = NULL;
|
||||
return;
|
||||
}
|
||||
wav->samples += count;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue