Commit e16dba8

Nick Faro committed on
Free instr maps after importing
commit e16dba8b1f05079bcd5b11a9642904a10a59310f parent 93d95ea
2 changed files +159−155
Modifiedsong.pas +0−2
@@ -573,8 +573,6 @@ begin
573 end; 573 end;
574 574
575 procedure DestroySong(var S: TSong); 575 procedure DestroySong(var S: TSong);
576 var
577 I: Integer;
578 begin 576 begin
579 S.Patterns.Free; 577 S.Patterns.Free;
580 end; 578 end;
Modifiedtbmimport.pas +159−153
@@ -354,197 +354,203 @@ var
354 NewInstId: Integer; 354 NewInstId: Integer;
355 TracksForCleanup: array of TTBMTrackFormat; 355 TracksForCleanup: array of TTBMTrackFormat;
356 begin 356 begin
357 InitializeSong(Result); 357 try
358 InitializeSong(Result);
358 359
359 Stream.ReadBuffer(Header, SizeOf(TTBMHeader)); 360 Stream.ReadBuffer(Header, SizeOf(TTBMHeader));
360 361
361 if Header.SCount > 1 then 362 if Header.SCount > 1 then
362 raise ETBMException.Create('hUGETracker only supports loading TBM modules with one song.'); 363 raise ETBMException.Create('hUGETracker only supports loading TBM modules with one song.');
363 364
364 // COMM block 365 // COMM block
365 Stream.ReadBuffer(BlockHeader, SizeOf(TTBMBlockHeader)); 366 Stream.ReadBuffer(BlockHeader, SizeOf(TTBMBlockHeader));
366 Stream.Seek(BlockHeader.Length, soCurrent); // Skip the comment for now 367 Stream.Seek(BlockHeader.Length, soCurrent); // Skip the comment for now
367 368
368 // SONG block 369 // SONG block
369 Stream.ReadBuffer(BlockHeader, SizeOf(TTBMBlockHeader)); 370 Stream.ReadBuffer(BlockHeader, SizeOf(TTBMBlockHeader));
370 Result.Name := Stream.ReadLString; 371 Result.Name := Stream.ReadLString;
371 Stream.ReadBuffer(SongFormat, SizeOf(TTBMSongFormat)); 372 Stream.ReadBuffer(SongFormat, SizeOf(TTBMSongFormat));
372 373
373 // Number of visible effect columns-- undocumented currently but I asked 374 // Number of visible effect columns-- undocumented currently but I asked
374 // stoneface about it. 375 // stoneface about it.
375 Stream.ReadByte; 376 Stream.ReadByte;
376 377
377 Result.TicksPerRow := SongFormat.RowsPerBeat; 378 Result.TicksPerRow := SongFormat.RowsPerBeat;
378 379
379 for I := Low(Result.OrderMatrix) to High(Result.OrderMatrix) do 380 for I := Low(Result.OrderMatrix) to High(Result.OrderMatrix) do
380 SetLength(Result.OrderMatrix[I], SongFormat.PatternCount+2); // off-by-one error on my part 381 SetLength(Result.OrderMatrix[I], SongFormat.PatternCount+2); // off-by-one error on my part
381 382
382 for I := 0 to SongFormat.PatternCount do begin 383 for I := 0 to SongFormat.PatternCount do begin
383 Result.OrderMatrix[0, I] := 100 + Stream.ReadByte; 384 Result.OrderMatrix[0, I] := 100 + Stream.ReadByte;
384 Result.OrderMatrix[1, I] := 200 + Stream.ReadByte; 385 Result.OrderMatrix[1, I] := 200 + Stream.ReadByte;
385 Result.OrderMatrix[2, I] := 300 + Stream.ReadByte; 386 Result.OrderMatrix[2, I] := 300 + Stream.ReadByte;
386 Result.OrderMatrix[3, I] := 400 + Stream.ReadByte; 387 Result.OrderMatrix[3, I] := 400 + Stream.ReadByte;
387 end; 388 end;
388 389
389 SetLength(TracksForCleanup, SongFormat.NumberOfTracks); 390 SetLength(TracksForCleanup, SongFormat.NumberOfTracks);
390 for I := 0 to SongFormat.NumberOfTracks-1 do begin 391 for I := 0 to SongFormat.NumberOfTracks-1 do begin
391 Stream.ReadBuffer(TrackFormat, SizeOf(TTBMTrackFormat)); 392 Stream.ReadBuffer(TrackFormat, SizeOf(TTBMTrackFormat));
392 TracksForCleanup[I] := TrackFormat; 393 TracksForCleanup[I] := TrackFormat;
393 394
394 case TrackFormat.Channel of 395 case TrackFormat.Channel of
395 0, 1: InsType := itSquare; 396 0, 1: InsType := itSquare;
396 2: InsType := itWave; 397 2: InsType := itWave;
397 3: InsType := itNoise; 398 3: InsType := itNoise;
398 end; 399 end;
399 400
400 Pat := Result.Patterns.GetOrCreateNew(((TrackFormat.Channel+1)*100) + TrackFormat.TrackId); 401 Pat := Result.Patterns.GetOrCreateNew(((TrackFormat.Channel+1)*100) + TrackFormat.TrackId);
401 for J := 0 to TrackFormat.Rows do begin 402 for J := 0 to TrackFormat.Rows do begin
402 Stream.ReadBuffer(RowFormat, SizeOf(TTBMRowFormat)); 403 Stream.ReadBuffer(RowFormat, SizeOf(TTBMRowFormat));
403 Pat^[RowFormat.RowNo] := ConverTBMRow(RowFormat.RowData, InsType); 404 Pat^[RowFormat.RowNo] := ConverTBMRow(RowFormat.RowData, InsType);
405 end;
404 end; 406 end;
405 end;
406 407
407 // INST block 408 // INST block
408 SquareMap := TTBMInstrumentMap.Create; 409 SquareMap := TTBMInstrumentMap.Create;
409 WaveMap := TTBMInstrumentMap.Create; 410 WaveMap := TTBMInstrumentMap.Create;
410 NoiseMap := TTBMInstrumentMap.Create; 411 NoiseMap := TTBMInstrumentMap.Create;
411 SeenSquare := 1; 412 SeenSquare := 1;
412 SeenWave := 1; 413 SeenWave := 1;
413 SeenNoise := 1; 414 SeenNoise := 1;
414 415
415 for I := 0 to Header.ICount-1 do begin 416 for I := 0 to Header.ICount-1 do begin
416 Stream.ReadBuffer(BlockHeader, SizeOf(TTBMBlockHeader)); 417 Stream.ReadBuffer(BlockHeader, SizeOf(TTBMBlockHeader));
417 418
418 InstId := Stream.ReadByte; 419 InstId := Stream.ReadByte;
419 InstName := Stream.ReadLString; 420 InstName := Stream.ReadLString;
420 421
421 Stream.ReadBuffer(InstFormat, SizeOf(TTBMInstrumentFormat)); 422 Stream.ReadBuffer(InstFormat, SizeOf(TTBMInstrumentFormat));
422 423
423 case InstFormat.Channel of 424 case InstFormat.Channel of
424 0, 1: begin 425 0, 1: begin
425 InsType := itSquare; 426 InsType := itSquare;
426 SquareMap.Add(InstId, SeenSquare); 427 SquareMap.Add(InstId, SeenSquare);
427 NewInstId := SeenSquare; 428 NewInstId := SeenSquare;
428 Inc(SeenSquare); 429 Inc(SeenSquare);
429 end; 430 end;
430 2: begin 431 2: begin
431 InsType := itWave; 432 InsType := itWave;
432 WaveMap.Add(InstId, SeenWave); 433 WaveMap.Add(InstId, SeenWave);
433 NewInstId := SeenWave; 434 NewInstId := SeenWave;
434 Inc(SeenWave); 435 Inc(SeenWave);
435 end; 436 end;
436 3: begin 437 3: begin
437 InsType := itNoise; 438 InsType := itNoise;
438 NoiseMap.Add(InstId, SeenNoise); 439 NoiseMap.Add(InstId, SeenNoise);
439 NewInstId := SeenNoise; 440 NewInstId := SeenNoise;
440 Inc(SeenNoise); 441 Inc(SeenNoise);
442 end;
441 end; 443 end;
442 end;
443 444
444 Ins := @Result.Instruments.All[UnmodInst(InsType, NewInstId)]; 445 Ins := @Result.Instruments.All[UnmodInst(InsType, NewInstId)];
445 Ins^.Name := InstName; 446 Ins^.Name := InstName;
446 447
447 EnvReg.ByteValue := InstFormat.Envelope; 448 EnvReg.ByteValue := InstFormat.Envelope;
448 Ins^.InitialVolume := EnvReg.InitialVolume; 449 Ins^.InitialVolume := EnvReg.InitialVolume;
449 if EnvReg.Direction then 450 if EnvReg.Direction then
450 Ins^.VolSweepDirection := stUp 451 Ins^.VolSweepDirection := stUp
451 else 452 else
452 Ins^.VolSweepDirection := stDown; 453 Ins^.VolSweepDirection := stDown;
453 Ins^.VolSweepAmount := EnvReg.SweepNumber; 454 Ins^.VolSweepAmount := EnvReg.SweepNumber;
454 Ins^.Waveform := InstFormat.Envelope; 455 Ins^.Waveform := InstFormat.Envelope;
455
456 Ins^.SubpatternEnabled := True;
457 456
458 // Arpeggio sequence 457 Ins^.SubpatternEnabled := True;
459 Stream.ReadBuffer(SeqFormat, SizeOf(TTBMSequenceFormat));
460 for J := 0 to SeqFormat.Length-1 do begin
461 Offs := ShortInt(Stream.ReadByte);
462 Ins^.Subpattern[J].Note := MIDDLE_NOTE + Offs;
463 end;
464 458
465 Ins^.Subpattern[SeqFormat.Length].Volume := SeqFormat.LoopIndex; 459 // Arpeggio sequence
460 Stream.ReadBuffer(SeqFormat, SizeOf(TTBMSequenceFormat));
461 for J := 0 to SeqFormat.Length-1 do begin
462 Offs := ShortInt(Stream.ReadByte);
463 Ins^.Subpattern[J].Note := MIDDLE_NOTE + Offs;
464 end;
466 465
467 // Panning sequence 466 Ins^.Subpattern[SeqFormat.Length].Volume := SeqFormat.LoopIndex;
468 Stream.ReadBuffer(SeqFormat, SizeOf(TTBMSequenceFormat));
469 Stream.Seek(SeqFormat.Length, soCurrent);
470 467
471 // Pitch sequence 468 // Panning sequence
472 Stream.ReadBuffer(SeqFormat, SizeOf(TTBMSequenceFormat)); 469 Stream.ReadBuffer(SeqFormat, SizeOf(TTBMSequenceFormat));
473 PitchOffset := 0; 470 Stream.Seek(SeqFormat.Length, soCurrent);
474 Offs := 0;
475 for J := 0 to SeqFormat.Length-1 do begin
476 Offs := ShortInt(Stream.ReadByte);
477 471
478 if Offs > PitchOffset then 472 // Pitch sequence
479 Ins^.Subpattern[J].EffectCode := $1 473 Stream.ReadBuffer(SeqFormat, SizeOf(TTBMSequenceFormat));
480 else if Offs < PitchOffset then 474 PitchOffset := 0;
481 Ins^.Subpattern[J].EffectCode := $2 475 Offs := 0;
482 else 476 for J := 0 to SeqFormat.Length-1 do begin
483 Continue; 477 Offs := ShortInt(Stream.ReadByte);
484 478
485 Ins^.Subpattern[J].EffectParams.Value := Abs(PitchOffset - Offs); 479 if Offs > PitchOffset then
486 PitchOffset := Offs; 480 Ins^.Subpattern[J].EffectCode := $1
487 end; 481 else if Offs < PitchOffset then
482 Ins^.Subpattern[J].EffectCode := $2
483 else
484 Continue;
488 485
489 Ins^.Subpattern[SeqFormat.Length].Volume := SeqFormat.LoopIndex; 486 Ins^.Subpattern[J].EffectParams.Value := Abs(PitchOffset - Offs);
487 PitchOffset := Offs;
488 end;
490 489
491 // Duty/noise-type sequence 490 Ins^.Subpattern[SeqFormat.Length].Volume := SeqFormat.LoopIndex;
492 Stream.ReadBuffer(SeqFormat, SizeOf(TTBMSequenceFormat)); 491
493 case InsType of 492 // Duty/noise-type sequence
494 itSquare: begin 493 Stream.ReadBuffer(SeqFormat, SizeOf(TTBMSequenceFormat));
495 for J := 0 to SeqFormat.Length-1 do begin 494 case InsType of
496 Ins^.Subpattern[J].EffectCode := $9; 495 itSquare: begin
497 case Stream.ReadByte of 496 for J := 0 to SeqFormat.Length-1 do begin
498 0: Ins^.Subpattern[J].EffectParams.Value := $00; 497 Ins^.Subpattern[J].EffectCode := $9;
499 1: Ins^.Subpattern[J].EffectParams.Value := $40; 498 case Stream.ReadByte of
500 2: Ins^.Subpattern[J].EffectParams.Value := $80; 499 0: Ins^.Subpattern[J].EffectParams.Value := $00;
501 3: Ins^.Subpattern[J].EffectParams.Value := $C0; 500 1: Ins^.Subpattern[J].EffectParams.Value := $40;
501 2: Ins^.Subpattern[J].EffectParams.Value := $80;
502 3: Ins^.Subpattern[J].EffectParams.Value := $C0;
503 end;
502 end; 504 end;
503 end; 505 end;
504 end; 506 itWave: begin
505 itWave: begin 507 for J := 0 to SeqFormat.Length-1 do begin
506 for J := 0 to SeqFormat.Length-1 do begin 508 Ins^.Subpattern[J].EffectCode := $C;
507 Ins^.Subpattern[J].EffectCode := $C; 509 case Stream.ReadByte of
508 case Stream.ReadByte of 510 0: Ins^.Subpattern[J].EffectParams.Value := $00;
509 0: Ins^.Subpattern[J].EffectParams.Value := $00; 511 1: Ins^.Subpattern[J].EffectParams.Value := $01;
510 1: Ins^.Subpattern[J].EffectParams.Value := $01; 512 2: Ins^.Subpattern[J].EffectParams.Value := $08;
511 2: Ins^.Subpattern[J].EffectParams.Value := $08; 513 3: Ins^.Subpattern[J].EffectParams.Value := $0F;
512 3: Ins^.Subpattern[J].EffectParams.Value := $0F; 514 end;
513 end; 515 end;
514 end; 516 end;
517 itNoise: begin
518 for J := 0 to SeqFormat.Length-1 do begin
519 Ins^.Subpattern[J].EffectCode := $9;
520 if Stream.ReadByte = 0 then
521 Ins^.Subpattern[J].EffectParams.Value := $00
522 else
523 Ins^.Subpattern[J].EffectParams.Value := $80;
524 end;
525 end
515 end; 526 end;
516 itNoise: begin
517 for J := 0 to SeqFormat.Length-1 do begin
518 Ins^.Subpattern[J].EffectCode := $9;
519 if Stream.ReadByte = 0 then
520 Ins^.Subpattern[J].EffectParams.Value := $00
521 else
522 Ins^.Subpattern[J].EffectParams.Value := $80;
523 end;
524 end
525 end;
526 527
527 Ins^.Subpattern[SeqFormat.Length].Volume := SeqFormat.LoopIndex; 528 Ins^.Subpattern[SeqFormat.Length].Volume := SeqFormat.LoopIndex;
528 end; 529 end;
529 530
530 // WAVE Block 531 // WAVE Block
531 for I := 0 to Header.WCount-1 do begin 532 for I := 0 to Header.WCount-1 do begin
532 Stream.ReadBuffer(BlockHeader, SizeOf(TTBMBlockHeader)); 533 Stream.ReadBuffer(BlockHeader, SizeOf(TTBMBlockHeader));
533 WaveId := Stream.ReadByte; 534 WaveId := Stream.ReadByte;
534 WaveName := Stream.ReadLString; 535 WaveName := Stream.ReadLString;
535 Stream.ReadBuffer(FourBitWave, SizeOf(T4bitWave)); 536 Stream.ReadBuffer(FourBitWave, SizeOf(T4bitWave));
536 Result.Waves[WaveId] := UnconvertWaveform(FourBitWave); 537 Result.Waves[WaveId] := UnconvertWaveform(FourBitWave);
537 end; 538 end;
538 539
539 // Cleanup patterns 540 // Cleanup patterns
540 for TrackFormat in TracksForCleanup do begin 541 for TrackFormat in TracksForCleanup do begin
541 Pat := Result.Patterns.GetOrCreateNew(((TrackFormat.Channel+1)*100) + TrackFormat.TrackId); 542 Pat := Result.Patterns.GetOrCreateNew(((TrackFormat.Channel+1)*100) + TrackFormat.TrackId);
542 543
543 case TrackFormat.Channel of 544 case TrackFormat.Channel of
544 0, 1: CleanupPattern(Pat, SquareMap); 545 0, 1: CleanupPattern(Pat, SquareMap);
545 2: CleanupPattern(Pat, WaveMap); 546 2: CleanupPattern(Pat, WaveMap);
546 3: CleanupPattern(Pat, NoiseMap); 547 3: CleanupPattern(Pat, NoiseMap);
548 end;
547 end; 549 end;
550 finally
551 if Assigned(SquareMap) then SquareMap.Free;
552 if Assigned(WaveMap) then WaveMap.Free;
553 if Assigned(NoiseMap) then NoiseMap.Free;
548 end; 554 end;
549 end; 555 end;
550 556