beta 1-3 .dmf loading
i did it
This commit is contained in:
		
							parent
							
								
									9e0e725802
								
							
						
					
					
						commit
						8a49522e59
					
				|  | @ -53,6 +53,10 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { | ||||||
|   warnings=""; |   warnings=""; | ||||||
|   try { |   try { | ||||||
|     DivSong ds; |     DivSong ds; | ||||||
|  |     unsigned char historicColIns[DIV_MAX_CHANS]; | ||||||
|  |     for (int i=0; i<DIV_MAX_CHANS; i++) { | ||||||
|  |       historicColIns[i]=i; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ds.nullWave.len=32; |     ds.nullWave.len=32; | ||||||
|     for (int i=0; i<32; i++) { |     for (int i=0; i<32; i++) { | ||||||
|  | @ -172,7 +176,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { | ||||||
| 
 | 
 | ||||||
|     ds.timeBase=reader.readC(); |     ds.timeBase=reader.readC(); | ||||||
|     ds.speed1=reader.readC(); |     ds.speed1=reader.readC(); | ||||||
|     if (ds.version>0x03) { |     if (ds.version>0x05) { | ||||||
|       ds.speed2=reader.readC(); |       ds.speed2=reader.readC(); | ||||||
|       ds.pal=reader.readC(); |       ds.pal=reader.readC(); | ||||||
|       ds.hz=(ds.pal)?60:50; |       ds.hz=(ds.pal)?60:50; | ||||||
|  | @ -258,7 +262,9 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { | ||||||
|       addWarning("Yamaha YMU759 emulation is incomplete! please migrate your song to the OPL3 system."); |       addWarning("Yamaha YMU759 emulation is incomplete! please migrate your song to the OPL3 system."); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     logI("reading pattern matrix (%d)...",ds.ordersLen); |     logV("%x",reader.tell()); | ||||||
|  | 
 | ||||||
|  |     logI("reading pattern matrix (%d * %d = %d)...",ds.ordersLen,getChannelCount(ds.system[0]),ds.ordersLen*getChannelCount(ds.system[0])); | ||||||
|     for (int i=0; i<getChannelCount(ds.system[0]); i++) { |     for (int i=0; i<getChannelCount(ds.system[0]); i++) { | ||||||
|       for (int j=0; j<ds.ordersLen; j++) { |       for (int j=0; j<ds.ordersLen; j++) { | ||||||
|         ds.orders.ord[i][j]=reader.readC(); |         ds.orders.ord[i][j]=reader.readC(); | ||||||
|  | @ -272,9 +278,14 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { | ||||||
|           ds.pat[i].getPattern(j,true)->name=reader.readString((unsigned char)reader.readC()); |           ds.pat[i].getPattern(j,true)->name=reader.readString((unsigned char)reader.readC()); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|  |       if (ds.version>0x03 && ds.version<0x06 && i<16) { | ||||||
|  |         historicColIns[i]=reader.readC(); | ||||||
|  |       } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (ds.version>0x03) { |     logV("%x",reader.tell()); | ||||||
|  | 
 | ||||||
|  |     if (ds.version>0x05) { | ||||||
|       ds.insLen=(unsigned char)reader.readC(); |       ds.insLen=(unsigned char)reader.readC(); | ||||||
|     } else { |     } else { | ||||||
|       ds.insLen=16; |       ds.insLen=16; | ||||||
|  | @ -282,7 +293,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { | ||||||
|     logI("reading instruments (%d)...",ds.insLen); |     logI("reading instruments (%d)...",ds.insLen); | ||||||
|     for (int i=0; i<ds.insLen; i++) { |     for (int i=0; i<ds.insLen; i++) { | ||||||
|       DivInstrument* ins=new DivInstrument; |       DivInstrument* ins=new DivInstrument; | ||||||
|       if (ds.version>0x03) { |       if (ds.version>0x05) { | ||||||
|         ins->name=reader.readString((unsigned char)reader.readC()); |         ins->name=reader.readString((unsigned char)reader.readC()); | ||||||
|       } |       } | ||||||
|       logD("%d name: %s",i,ins->name.c_str()); |       logD("%d name: %s",i,ins->name.c_str()); | ||||||
|  | @ -319,6 +330,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       if (ins->mode) { // FM
 |       if (ins->mode) { // FM
 | ||||||
|  |         if (ds.version>0x05) { | ||||||
|           ins->fm.alg=reader.readC(); |           ins->fm.alg=reader.readC(); | ||||||
|           if (ds.version<0x13) { |           if (ds.version<0x13) { | ||||||
|             reader.readC(); |             reader.readC(); | ||||||
|  | @ -335,13 +347,24 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { | ||||||
|           } else { |           } else { | ||||||
|             ins->fm.ops=4; |             ins->fm.ops=4; | ||||||
|           } |           } | ||||||
|  |           ins->fm.ams=reader.readC(); | ||||||
|  |         } else { | ||||||
|  |           ins->fm.alg=reader.readC(); | ||||||
|  |           reader.readC(); | ||||||
|  |           ins->fm.fb=reader.readC(); | ||||||
|  |           reader.readC(); // apparently an index of sorts starting from 0x59?
 | ||||||
|  |           ins->fm.fms=reader.readC(); | ||||||
|  |           reader.readC(); // 0x59+index?
 | ||||||
|  |           ins->fm.ops=2+reader.readC()*2; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         logD("ALG %d FB %d FMS %d AMS %d OPS %d",ins->fm.alg,ins->fm.fb,ins->fm.fms,ins->fm.ams,ins->fm.ops); | ||||||
|         if (ins->fm.ops!=2 && ins->fm.ops!=4) { |         if (ins->fm.ops!=2 && ins->fm.ops!=4) { | ||||||
|           logE("invalid op count %d. did we read it wrong?",ins->fm.ops); |           logE("invalid op count %d. did we read it wrong?",ins->fm.ops); | ||||||
|           lastError="file is corrupt or unreadable at operators"; |           lastError="file is corrupt or unreadable at operators"; | ||||||
|           delete[] file; |           delete[] file; | ||||||
|           return false; |           return false; | ||||||
|         } |         } | ||||||
|         ins->fm.ams=reader.readC(); |  | ||||||
| 
 | 
 | ||||||
|         for (int j=0; j<ins->fm.ops; j++) { |         for (int j=0; j<ins->fm.ops; j++) { | ||||||
|           ins->fm.op[j].am=reader.readC(); |           ins->fm.op[j].am=reader.readC(); | ||||||
|  | @ -385,7 +408,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { | ||||||
|               ins->fm.op[j].dt2=reader.readC(); |               ins->fm.op[j].dt2=reader.readC(); | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
|           if (ds.version>0x03) { |           if (ds.version>0x05) { | ||||||
|             if (ds.system[0]==DIV_SYSTEM_SMS_OPLL || ds.system[0]==DIV_SYSTEM_NES_VRC7) { |             if (ds.system[0]==DIV_SYSTEM_SMS_OPLL || ds.system[0]==DIV_SYSTEM_NES_VRC7) { | ||||||
|               ins->fm.op[j].ksr=reader.readC(); |               ins->fm.op[j].ksr=reader.readC(); | ||||||
|               ins->fm.op[j].vib=reader.readC(); |               ins->fm.op[j].vib=reader.readC(); | ||||||
|  | @ -588,6 +611,8 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     logV("%x",reader.tell()); | ||||||
|  | 
 | ||||||
|     logI("reading patterns (%d channels, %d orders)...",getChannelCount(ds.system[0]),ds.ordersLen); |     logI("reading patterns (%d channels, %d orders)...",getChannelCount(ds.system[0]),ds.ordersLen); | ||||||
|     for (int i=0; i<getChannelCount(ds.system[0]); i++) { |     for (int i=0; i<getChannelCount(ds.system[0]); i++) { | ||||||
|       DivChannelData& chan=ds.pat[i]; |       DivChannelData& chan=ds.pat[i]; | ||||||
|  | @ -595,7 +620,6 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { | ||||||
|         chan.effectRows=1; |         chan.effectRows=1; | ||||||
|       } else { |       } else { | ||||||
|         chan.effectRows=reader.readC(); |         chan.effectRows=reader.readC(); | ||||||
|          |  | ||||||
|       } |       } | ||||||
|       logD("%d fx rows: %d",i,chan.effectRows); |       logD("%d fx rows: %d",i,chan.effectRows); | ||||||
|       if (chan.effectRows>4 || chan.effectRows<1) { |       if (chan.effectRows>4 || chan.effectRows<1) { | ||||||
|  | @ -606,6 +630,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { | ||||||
|       } |       } | ||||||
|       for (int j=0; j<ds.ordersLen; j++) { |       for (int j=0; j<ds.ordersLen; j++) { | ||||||
|         DivPattern* pat=chan.getPattern(ds.orders.ord[i][j],true); |         DivPattern* pat=chan.getPattern(ds.orders.ord[i][j],true); | ||||||
|  |         if (ds.version>0x05) { // current pattern format
 | ||||||
|           for (int k=0; k<ds.patLen; k++) { |           for (int k=0; k<ds.patLen; k++) { | ||||||
|             // note
 |             // note
 | ||||||
|             pat->data[k][0]=reader.readS(); |             pat->data[k][0]=reader.readS(); | ||||||
|  | @ -672,13 +697,43 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { | ||||||
|               } |               } | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
|  |         } else { // historic pattern format
 | ||||||
|  |           if (i<16) pat->data[0][2]=historicColIns[i]; | ||||||
|  |           for (int k=0; k<ds.patLen; k++) { | ||||||
|  |             // note
 | ||||||
|  |             pat->data[k][0]=reader.readC(); | ||||||
|  |             // octave
 | ||||||
|  |             pat->data[k][1]=reader.readC(); | ||||||
|  |             if (pat->data[k][0]!=0) { | ||||||
|  |               // YMU759 is stored 2 octaves lower
 | ||||||
|  |               pat->data[k][1]+=2; | ||||||
|  |             } | ||||||
|  |             if (pat->data[k][0]==0 && pat->data[k][1]!=0) { | ||||||
|  |               logD("what? %d:%d:%d note %d octave %d",i,j,k,pat->data[k][0],pat->data[k][1]); | ||||||
|  |               pat->data[k][0]=12; | ||||||
|  |               pat->data[k][1]--; | ||||||
|  |             } | ||||||
|  |             // volume and effect
 | ||||||
|  |             unsigned char vol=reader.readC(); | ||||||
|  |             unsigned char fx=reader.readC(); | ||||||
|  |             unsigned char fxVal=reader.readC(); | ||||||
|  |             pat->data[k][3]=(vol==0x80)?-1:vol; | ||||||
|  |             // effect
 | ||||||
|  |             pat->data[k][4]=(fx==0x80)?-1:fx; | ||||||
|  |             pat->data[k][5]=(fxVal==0x80)?-1:fxVal; | ||||||
|  |             // instrument wasn't stored back then
 | ||||||
|  |           } | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     int ymuSampleRate=20; | ||||||
|  | 
 | ||||||
|     ds.sampleLen=(unsigned char)reader.readC(); |     ds.sampleLen=(unsigned char)reader.readC(); | ||||||
|     logI("reading samples (%d)...",ds.sampleLen); |     logI("reading samples (%d)...",ds.sampleLen); | ||||||
|     if (ds.version<0x0b && ds.sampleLen>0) { // TODO what is this for?
 |     if (ds.version<0x0b && ds.sampleLen>0) { | ||||||
|       reader.readC(); |       // it appears this byte stored the YMU759 sample rate
 | ||||||
|  |       ymuSampleRate=reader.readC(); | ||||||
|     } |     } | ||||||
|     for (int i=0; i<ds.sampleLen; i++) { |     for (int i=0; i<ds.sampleLen; i++) { | ||||||
|       DivSample* sample=new DivSample; |       DivSample* sample=new DivSample; | ||||||
|  | @ -686,6 +741,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { | ||||||
|       int pitch=5; |       int pitch=5; | ||||||
|       int vol=50; |       int vol=50; | ||||||
|       short* data; |       short* data; | ||||||
|  |       unsigned char* adpcmData; | ||||||
|       if (length<0) { |       if (length<0) { | ||||||
|         logE("invalid sample length %d. are we doing something wrong?",length); |         logE("invalid sample length %d. are we doing something wrong?",length); | ||||||
|         lastError="file is corrupt or unreadable at samples"; |         lastError="file is corrupt or unreadable at samples"; | ||||||
|  | @ -704,6 +760,9 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { | ||||||
|         pitch=reader.readC(); |         pitch=reader.readC(); | ||||||
|         vol=reader.readC(); |         vol=reader.readC(); | ||||||
|       } |       } | ||||||
|  |       if (ds.version<=0x05) { | ||||||
|  |         sample->rate=ymuSampleRate*400; | ||||||
|  |       } | ||||||
|       if (ds.version>0x15) { |       if (ds.version>0x15) { | ||||||
|         sample->depth=reader.readC(); |         sample->depth=reader.readC(); | ||||||
|         if (sample->depth!=8 && sample->depth!=16) { |         if (sample->depth!=8 && sample->depth!=16) { | ||||||
|  | @ -711,9 +770,15 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { | ||||||
|           sample->depth=16; |           sample->depth=16; | ||||||
|         } |         } | ||||||
|       } else { |       } else { | ||||||
|  |         if (ds.version>0x05) { | ||||||
|           sample->depth=16; |           sample->depth=16; | ||||||
|  |         } else { | ||||||
|  |           // it appears samples were stored as ADPCM back then
 | ||||||
|  |           sample->depth=6; | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|       if (length>0) { |       if (length>0) { | ||||||
|  |         if (ds.version>0x05) { | ||||||
|           if (ds.version<0x0b) { |           if (ds.version<0x0b) { | ||||||
|             data=new short[1+(length/2)]; |             data=new short[1+(length/2)]; | ||||||
|             reader.read(data,length); |             reader.read(data,length); | ||||||
|  | @ -748,6 +813,22 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { | ||||||
|           } |           } | ||||||
| 
 | 
 | ||||||
|           delete[] data; |           delete[] data; | ||||||
|  |         } else { | ||||||
|  |           // ADPCM?
 | ||||||
|  |           // it appears to be a slightly modified version of ADPCM-B!
 | ||||||
|  |           adpcmData=new unsigned char[length]; | ||||||
|  |           logV("%x",reader.tell()); | ||||||
|  |           reader.read(adpcmData,length); | ||||||
|  |           for (int i=0; i<length; i++) { | ||||||
|  |             adpcmData[i]=(adpcmData[i]<<4)|(adpcmData[i]>>4); | ||||||
|  |           } | ||||||
|  |           if (!sample->init(length*2)) { | ||||||
|  |             logE("%d: error while initializing sample!",i); | ||||||
|  |           } | ||||||
|  | 
 | ||||||
|  |           memcpy(sample->dataB,adpcmData,length); | ||||||
|  |           delete[] adpcmData; | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|       ds.sample.push_back(sample); |       ds.sample.push_back(sample); | ||||||
|     } |     } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 tildearrow
						tildearrow