diff --git a/5F_MIB2_Dataset_0x003000.BIN.bt b/5F_MIB2_Dataset_0x003000.BIN.bt index 2b5c427..3439d96 100644 --- a/5F_MIB2_Dataset_0x003000.BIN.bt +++ b/5F_MIB2_Dataset_0x003000.BIN.bt @@ -3,33 +3,35 @@ // // File: 0x003000.BIN // Authors: Alex Strelets -// Version: 0.5 +// Version: 0.6 // Purpose: Parse the contents of the MIB2 Sound Channels and Effects // Category: // File Mask: // ID Bytes: -// History: 0.1 - Initial version -// 0.2 - Limiters added -// 0.3 - MIB1 vs MIB2 data sync -// 0.5 - 'Sound Effects' table optimizations, -// renaming, refactoring, cleanup +// History: 0.1 - Initial version +// 0.2 - Limiters added +// 0.3 - MIB1 vs MIB2 data sync +// 0.5 - 'Sound Effects' table optimizations, +// renaming, refactoring, cleanup // 0.5.1 - THD max property found +// 0.6 - Cosmetic output changes, +// corrected delay calculation //------------------------------------------------ BigEndian(); -string getSignalflow(int type) { +string getAmpMode(int type) { switch (type) { - case 0x10: return "2ch (4.0)"; - case 0x20: return "4ch (8.0)"; - case 0x21: return "4ch / 2ch compatible (8.0 / 4.0)"; - case 0x25: return "5ch center (9.0)"; - case 0x30: return "6ch center sub (9.1)"; - case 0x31: return "6ch center sub / 2/4ch compatible (9.1 / 8.0 / 4.0)"; - case 0x32: return "6ch doublesub (8.2)"; - case 0x33: return "6ch doublesub / 2/4ch compatible (8.2 / 8.0 / 4.0)"; - case 0x34: return "6ch frontwoofer (9.1)"; - case 0x35: return "6ch frontwoofer / 2/4ch compatible (9.1 / 8.0 / 4.0)"; + case 0x10: return "2 channels - front"; + case 0x20: return "4 channels - front/rear"; + case 0x21: return "4ch / 2ch compatible"; + case 0x25: return "5ch - front/rear/center"; + case 0x30: return "6ch - front/rear/center DVC sub"; + case 0x31: return "6ch - front/rear/center DVC sub / 2/4ch compatible"; + case 0x32: return "6ch double SVC or DVC sub"; + case 0x33: return "6ch double SVC or DVC sub"; + case 0x34: return "6ch - lows/mids/highs, no rear speakers"; + case 0x35: return "6ch - lows/mids/highs, no rear speakers / 2/4ch compatible"; default: return "Unknown"; } } @@ -37,42 +39,42 @@ string getSignalflow(int type) { string getFilterType(int type) { switch (type) { case 0x00: return "Bypass"; - case 0x01: return "Shelf 1 High"; - case 0x02: return "Shelf 2 High"; - case 0x03: return "Shelf 1 Low"; - case 0x04: return "Shelf 2 Low"; - case 0x05: return "Peak 1"; - case 0x06: return "Peak 2"; + case 0x01: return "High Shelf 1"; + case 0x02: return "High Shelf 2"; + case 0x03: return "Low Shelf 1"; + case 0x04: return "Low Shelf 2"; + case 0x05: return "INVALID"; + case 0x06: return "Peak"; case 0x07: return "Highpass 1"; case 0x08: return "Highpass 2"; case 0x09: return "Lowpass 1"; case 0x0A: return "Lowpass 2"; - case 0x10: return "Coefficients"; + case 0x10: return "INVALID"; default: return "Unknown"; } } typedef struct { - ubyte type ; - ubyte quality ; // [0.2 .. 5] - ushort frequency ; // [20 .. 20000] - ubyte gainOffset ; // [-6 .. +6] - ubyte maxGain ; // [0 .. 15] + ubyte Type ; + ubyte Quality ; // [0.2 .. 5] + ushort Frequency ; // [20 .. 20000] + ubyte GainOffset ; // [-6 .. +6] + ubyte MaxGain ; // [0 .. 15] } EQ; typedef struct { - ubyte type ; - ubyte quality ; - ushort frequency ; - ubyte gain[19] ; + ubyte Type ; + ubyte Quality ; + ushort Frequency ; + ubyte Gain[19] ; } EQ2; typedef struct (int length) { - ubyte type ; - ubyte quality ; - ushort frequency ; - byte gain ; // [-12.5 .. 12.5] - ubyte coefficients[length] ; + ubyte Type ; + ubyte Quality ; + ushort Frequency ; + byte Gain ; // [-12.5 .. 12.5] + ubyte Coefficients[length] ; } EQ3; typedef struct { @@ -84,7 +86,7 @@ typedef struct { EQ3 Filter6(0); EQ3 Filter7(0); byte Gain ; - ubyte Delay ; + byte Delay ; ubyte Phase ; } CarEQ; @@ -104,25 +106,29 @@ float calcMaxGain (ubyte value) { return (float) value / 15; } +float calcDelay (byte value) { + return (float) value / 10; +} + void printEQ2(EQ2 &s, string name, int unknownFlag) { Printf("\n%s", name); - Printf("\nType \tQ Factor\tFrequency\n"); + Printf("\nType \t Quality Frequency\n"); Printf("==================================\n"); - Printf("%-13s%7.1f\t %6gHz\n", - getFilterType(s.type), - calcQuality(s.quality), - s.frequency); + Printf("%-13s%7.1f %6gHz\n", + getFilterType(s.Type), + calcQuality(s.Quality), + s.Frequency); Printf("==================================\n"); if (!unknownFlag) { Printf("Volume: \t"); for (i = 0; i < 19; i++) { - Printf("%5g ", 18 - i); + Printf("%5g ", 18 - i); } Printf("\n"); } Printf("Gain: \t"); for (i = 0; i < 19; i++) { - Printf("%5.2f ", calcAbsGain(s.gain[i])); + Printf("%5.2fdB ", calcAbsGain(s.Gain[i])); } Printf("\n"); } @@ -131,54 +137,54 @@ local string spacer = "\t\t\t"; void printEQFilter(EQ3 &filter, int index) { local string str = (index > 1 ? "\n" : spacer); - Printf("%-13s %5.1f\t %6gHz\t %5.2f %s", - getFilterType(filter.type), - calcQuality(filter.quality), - filter.frequency, - calcGain(filter.gain), + Printf("%-13s %5.1f %6gHz\t%5.2fdB %s", + getFilterType(filter.Type), + calcQuality(filter.Quality), + filter.Frequency, + calcGain(filter.Gain), str); } void printProfileName (int index) { - Printf("[ CarEQ SoundProfile #%i ] %s", index, index > 1 ? "\n\n": spacer); + Printf("[CarEQ Profile #%i] %s", index, index > 1 ? "\n\n": spacer); } string getChannelName(int index) { switch (index) { - case 0: return "REAR_R_CH "; break; - case 1: return "FRONT_R_CH"; break; - case 2: return "FRONT_L_CH"; break; - case 3: return "REAR_L_CH "; break; - case 4: return "SUBWOOFER "; break; - case 5: return "CENTER_CH "; break; + case 0: return "REAR_RIGHT "; break; + case 1: return "FRONT_RIGHT"; break; + case 2: return "FRONT_LEFT "; break; + case 3: return "REAR_LEFT "; break; + case 4: return "SUBWOOFER "; break; + case 5: return "CENTER "; break; } - return Str("CHANNEL_%i ", index+1); + return Str("CHANNEL_%i", index+1); } string getEQBand(int index) { switch (index) { - case 0: return "Bass"; break; - case 1: return "MidBass "; break; - case 2: return "Middle"; break; - case 3: return "MidTreble"; break; - case 4: return "Treble"; break; + case 0: return "Bass "; break; + case 1: return "Mid-Bass "; break; + case 2: return "Mid "; break; + case 3: return "Mid-Treble"; break; + case 4: return "Treble "; break; } - return Str("Band_%i ", index+1); + return Str("Band_%i", index+1); } void printChannelHeader(CarEQ eq[], int index, int profileIndex) { local string str = (profileIndex > 1 ? "\n" : spacer); - Printf("%s [ Gain: %-6.2f Delay: %-2gms Phase: %s ]%s", + Printf("%s [Gain: %-6.2fdB Delay: %2gms Phase: %s°]%s", getChannelName(index), calcGain(eq[index].Gain), - (float) eq[index].Delay, + calcDelay(eq[index].Delay), (char) eq[index].Phase > 0 ? 'R' : '0', str); } void printLines() { - local string str = "------------------------------------------------%s"; + local string str = "-------------------------------------------------------%s"; Printf(str, spacer); Printf(str, "\n"); } @@ -190,30 +196,30 @@ void printDoubleLines() { } void printFiltersHeader() { - local string str = "Type \tQ Factor\t Frequency\t Gain %s"; + local string str = "Type \t Quality Frequency\t Gain %s"; Printf(str, spacer); Printf(str, "\n"); } -byte Signalflow ; +byte AmpMode ; EQ ToneControls[5]; -ubyte Subwoofer_maxGain ; // subwoofer gain ??? +ubyte Subwoofer_MaxGain ; EQ2 LoudnessLow; EQ2 LoudnessHigh; struct { ubyte value[19] ; } GALA[7]; -EQ2 UnknownFilter_1; -EQ2 UnknownFilter_2; -CarEQ Profile_1[6] ; -CarEQ Profile_2[6] ; +EQ2 VirtualSub; +EQ2 GADKSurround; +CarEQ Profile1[6] ; +CarEQ Profile2[6] ; -// one of those bytes could be "Limiter THDmax" [0 .. 30] +// one of those bytes is "Limiter MaxTHD" [0 .. 70] struct { byte unknown[6] ; - byte THDmax ; -} Limiters; // Warmth ??? potentially + byte MaxTHD ; +} Limiters; struct { ubyte attackTime ; @@ -238,29 +244,36 @@ local int i = 0; local int j = 0; local int k = 0; -Printf("\nSIGNAL FLOW: %s\n", getSignalflow(Signalflow)); +local ushort file_checksum = Checksum(CHECKSUM_CRCCCITT, 0, FileSize() - 2, -1, -1); // algo, size, length, poly, init +Printf("================================================"); +Printf("\nFILE CHECKSUM (TO BE CORRECTED MANUALLY!): %.04X \n", file_checksum); +Printf("================================================"); +Printf("\n\nAMPLIFIER MODE: %s\n", getAmpMode(AmpMode)); -Printf("\nEQ TONE CONTROLS"); -Printf("\nBand \tType \tQ Factor\tFrequency\t MaxGain\tGainOffset\n"); -Printf("=======================================================================\n"); +Printf("\n\nTONE CONTROLS"); +Printf("\nBand\t Type\t\tQuality\t Frequency MaxGain GainOffset\n"); +Printf("===========================================================================\n"); +Printf("Subwoofer \t\t %7.2f\n", calcMaxGain(Subwoofer_MaxGain)); for (i = 0; i < 5; i++) { - Printf("%-8s\t%-13s%7.1f\t %6gHz\t %7.2f\t%10.2f\n", + Printf("%-8s %-13s %7.1f\t %6gHz\t %7.2f\t%10.2f\n", getEQBand(i), - getFilterType(ToneControls[i].type), - calcQuality(ToneControls[i].quality), - ToneControls[i].frequency, - calcMaxGain(ToneControls[i].maxGain), - ToneControls[i].gainOffset / 12); + getFilterType(ToneControls[i].Type), + calcQuality(ToneControls[i].Quality), + ToneControls[i].Frequency, + calcMaxGain(ToneControls[i].MaxGain), + ToneControls[i].GainOffset / 12); } -Printf("=======================================================================\n"); -Printf("Subwoofer \t %7.2f\n", calcMaxGain(Subwoofer_maxGain)); +Printf("===========================================================================\n\n\n"); + -printEQ2(LoudnessLow, "LOUDNESS LOW", false); -printEQ2(LoudnessHigh, "LOUDNESS HIGH", false); +printEQ2(LoudnessLow, "LOUDNESS - Bass Boost", false); +printEQ2(LoudnessHigh, "LOUDNESS - Treble Boost", false); +printEQ2(VirtualSub, "Virtual Sub", true); +printEQ2(GADKSurround, "GADK-Surround", true); -Printf("\nGALA (SPEED-DEPENDENT VOLUME CONTROL)"); -Printf("\nLevel \t Gain\n"); +Printf("\n\n\nGALA (SPEED-DEPENDENT VOLUME CONTROL)"); +Printf("\nVolume \t Gain steps (dB)\n"); Printf("=========================================="); Printf("=========================================="); Printf("==========================================\n"); @@ -273,61 +286,58 @@ for ( i = 0; i < 7; i++ ) { }; Printf("=========================================="); Printf("=========================================="); -Printf("==========================================\n"); - -printEQ2(UnknownFilter_1, "UNKNOWN FILTER 1", true); -printEQ2(UnknownFilter_2, "UNKNOWN FILTER 2", true); +Printf("==========================================\n\n"); -Printf("\n"); +Printf("\n\n"); printProfileName(1); printProfileName(2); for (i = 0; i < 6; i++) { - printChannelHeader(Profile_1, i, 1); - printChannelHeader(Profile_2, i, 2); + printChannelHeader(Profile1, i, 1); + printChannelHeader(Profile2, i, 2); printLines(); printFiltersHeader(); printDoubleLines(); - printEQFilter(Profile_1[i].Filter1, 1); - printEQFilter(Profile_2[i].Filter1, 2); - printEQFilter(Profile_1[i].Filter2, 1); - printEQFilter(Profile_2[i].Filter2, 2); - printEQFilter(Profile_1[i].Filter3, 1); - printEQFilter(Profile_2[i].Filter3, 2); - printEQFilter(Profile_1[i].Filter4, 1); - printEQFilter(Profile_2[i].Filter4, 2); - printEQFilter(Profile_1[i].Filter5, 1); - printEQFilter(Profile_2[i].Filter5, 2); - printEQFilter(Profile_1[i].Filter6, 1); - printEQFilter(Profile_2[i].Filter6, 2); - printEQFilter(Profile_1[i].Filter7, 1); - printEQFilter(Profile_2[i].Filter7, 2); + printEQFilter(Profile1[i].Filter1, 1); + printEQFilter(Profile2[i].Filter1, 2); + printEQFilter(Profile1[i].Filter2, 1); + printEQFilter(Profile2[i].Filter2, 2); + printEQFilter(Profile1[i].Filter3, 1); + printEQFilter(Profile2[i].Filter3, 2); + printEQFilter(Profile1[i].Filter4, 1); + printEQFilter(Profile2[i].Filter4, 2); + printEQFilter(Profile1[i].Filter5, 1); + printEQFilter(Profile2[i].Filter5, 2); + printEQFilter(Profile1[i].Filter6, 1); + printEQFilter(Profile2[i].Filter6, 2); + printEQFilter(Profile1[i].Filter7, 1); + printEQFilter(Profile2[i].Filter7, 2); printDoubleLines(); - Printf("\n"); + Printf("\n\n"); } -Printf("LIMITERS\n"); -Printf("\t\t\t THD\n"); +Printf("LIMITERS"); +Printf("\t\t\t THD\n"); Printf("----------------------------------------------\n"); for (i = 0; i < 6; i++) { - Printf("%3i ", Limiters.unknown[i]); + Printf("%3i ", Limiters.unknown[i]); } -Printf("%3i", Limiters.THDmax); +Printf("| %3i", Limiters.MaxTHD); Printf("\n\n"); -Printf("DYNAMIC RANGE COMPRESSION\n"); -Printf("Channel Threshold Attack Hold Release\n"); -Printf("================================================\n"); +Printf("DYNAMIC RANGE COMPRESSION (DRC)\n"); +Printf("Channel Threshold Attack Hold Release\n"); +Printf("======================================================\n"); for (i = 0; i < 6; i++) { - Printf("%s %5.1fdB %6.1f %6.1f %4gms\n", + Printf("%s %5.1fdB %6.1fms %6.1fms %4gms\n", getChannelName(i), - DRC[i].threshold / -20, // [-20 .. 0 ] - (float) DRC[i].attackTime / 20, // [0.5 .. 20] - (float) DRC[i].holdTime / 20, // [0.5 .. 20] - DRC[i].releaseTime // [5 .. 2000] + DRC[i].threshold / -20, // [-20 .. 0] + (float) DRC[i].attackTime / 20, // [0.5 .. 10] + (float) DRC[i].holdTime / 20, // [0 .. 20] + DRC[i].releaseTime // [5 .. 1000] ); } -Printf("================================================"); - -local ushort file_checksum = Checksum(CHECKSUM_CRCCCITT, 0, FileSize() - 2, -1, -1); // algo, size, length, poly, init -Printf("\n\nFILE CHECKSUM: %.04X", file_checksum); +Printf("======================================================"); +Printf("\n\n\n================================================"); +Printf("\nFILE CHECKSUM (TO BE CORRECTED MANUALLY!): %.04X", file_checksum); +Printf("\n================================================");