[PYTHON] Sound Font Mapping Problem

Dieser Artikel stammt aus Music Tools / Libraries / Technologies Adventskalender 2019 12/24.

(Dieses Mal habe ich es in Eile vorbereitet, sodass es möglicherweise nicht ein wenig zum Zweck passt. Nächstes Jahr möchte ich meine eigene Tonquelle und Sprachkomprimierung durchführen.

Einführung

Ich benutze DTM seit langer Zeit mit der Kombination aus Music Studio Producer, die vor 10 Jahren eingeführt wurde, und Timidity ++ und SoundFont, die vor 8 Jahren eingeführt wurde. Aufgrund des Kompatibilitätsproblems zwischen dem nicht aktualisierten MIDI-Treiber von Timidity und Windows 10 haben wir uns schließlich entschlossen, Timidity ...

Vor zehn Jahren habe ich eine Zuordnungsdatei manuell erstellt, aber in den letzten 10 Jahren habe ich die Programmierung unterstützt. Dieses Mal spreche ich davon, eine komfortable DTM-Umgebung mit der Leistung des Programms zu schaffen.

Sound Font Mapping

Wenn Sie eine Soundschrift in einer DAW verwenden, die nur MIDI verarbeiten kann, verwenden Sie eine virtuelle Soundquelle, die eine Soundschrift wie Timidity als MIDI-Soundquelle verwenden kann. Der Ton der Sound-Schriftart kann durch Kombinieren von ** Banknummer und voreingestellter Nummer ** festgelegt werden, und jeder Ton in der Sound-Schriftart kann durch eine MIDI-Meldung festgelegt werden, die der ** Bankauswahl und Programmänderung ** von MIDI entspricht. Du kannst wählen.

Wenn jedoch mehrere Sound-Schriftarten gleichzeitig verwendet werden, können Bänke und voreingestellte Nummern kollidieren, und je nach Sound-Schriftart kann sich die Anordnung der von MIDI angegebenen Töne erheblich unterscheiden, was unpraktisch ist und eine Zuordnung durchgeführt wird.

Glücklicherweise hat Timidity diese Funktion und wir haben sie zur Vereinfachung platziert. (Da ich es zu diesem Zeitpunkt als Benutzer verwendet habe, kannte ich das Dateiformat der Sound-Schriftart natürlich nicht und war mit MIDI nicht vertraut.)

Platzieren Sie die Töne in Excel in einem Bereich von 256 * 256 und stimmen Sie mit der Einstellungsdatei für die Schüchternheit und der DAW-Tondatei überein (Entsprechungstabelle mit Instrumentenname, Programmnummer, Banknummer. Wenn festgelegt, wird der Instrumentenname auf der DAW-GUI angezeigt. Ich habe es erstellt, weil es angezeigt wird.) Ich habe es von Hand geschrieben. image.png

Es gab viele Sound-Schriftarten, die ich hinzufügen wollte, aber ich habe sie in Excel zugewiesen und die Einstellungsdatei von Hand hinzugefügt ... es ist ärgerlich.

Von der Schüchternheit zum virtuellen MIDI-Synth

Nach einem großen Update von Win10 in diesem Sommer funktionierte Timidity ++ endlich nicht mehr. Erstens läuft Timidity ++ mit einem nicht signierten Treiber und es wurde nicht aktualisiert, daher dachte ich, es würde bald das Limit sein und umgeschaltet

Wir haben Virtual MIDI Synth als virtuelle MIDI-Soundquelle für das Übertragungsziel eingeführt.

** Es gibt jedoch keine Sound Font Mapping-Funktion **. Es ist möglich, Sound-Fonts aus mehreren Dateien zu laden, aber es scheint, dass der Sound der Sound-Font-Datei mit hoher Priorität im Falle einer Kollision verwendet wird. Das war ein Problem.

Schreiben wir also die Sound-Font-Datei neu, um Kollisionen zu vermeiden, und generieren dann automatisch die Tonzuordnung. <Lange Einführung

Spezifikation

Ich habe das Löschen der Tonfarbe hinzugefügt, da einige der Sound-Font-Dateien Müllton-Farbdaten enthielten, und das Weglassen des Tonfarbnamens wurde hinzugefügt, weil der Tonfarbname zu lang war und die DAW-Anzeige seltsam wurde.

Beachten Sie, dass die Konfigurationsdateien Music Studio Producer und Virtual MIDI Synth hier nicht erläutert werden.

Struktur der Sound-Schriftdatei

Technische Daten: http://freepats.zenvoid.org/sf2/sfspec24.pdf

Sound-Schriftarten werden im RIFF-Format gespeichert. RIFF speichert Daten in Einheiten, die als Chunks bezeichnet werden, und Chunks bestehen aus ID, Größe und Daten.

RIFF-Struktur

** Grundstruktur von Brocken **

Artikel Größe Bemerkungen
Chunk ID 4byte Chunk-ID(RIFF/LISTE usw.)
Datengröße 4byte Datengröße (Little Tordian))
Daten Nbyte

Darüber hinaus werden der erste Block, der RIFF-Block und der LIST-Block, der mehrere Blöcke kombiniert, als spezielle Blöcke vorbereitet. (Andere Chunks als RIFF und LIST dürfen keine Chunks enthalten.)

** RIFF-Blockstruktur **

Artikel Größe Bemerkungen
Chunk ID 4byte RIFF
Datengröße 4byte N+4
Dateikennung 4byte Kennung der in der RIFF-Datei gespeicherten Daten(Für Soundschriften sfbk)
Daten Nbyte Enthält Chunks und LIST-Chunks

** LIST Chunk Struktur **

Artikel Größe Bemerkungen
Chunk ID 4byte LIST
Datengröße 4byte N+4
Listenkennung 4byte Kennung der in der Liste gespeicherten Daten(INFO/Daten usw.)
Daten Nbyte Enthält Chunks und LIST-Chunks

RIFF-Dateien können diese Blöcke verwenden, um verschachtelte Strukturdaten darzustellen. image.png

Da die Größe des Datenteils am Anfang aller Chunks geschrieben wird, können unnötige Chunks übersprungen werden. Daher kann der Zweck erreicht werden, indem implementiert wird, dass nur die Chunks, die sich auf die Banknummer und die voreingestellte Nummer der Chunks der Soundschrift beziehen, verarbeitet werden und die Chunks danach so wie sie sind übersprungen werden.

RIFF-Struktur der Sounddatei

Die RIFF-Struktur der Soundschrift ist wie folgt. Von diesen enthalten die Chunks unter pdta den Instrumentennamen und die voreingestellte Nummer. image.png

pdta enthält Unterblöcke für ** Presets **, ** Instrumente ** und ** Samples **. Von diesen ist ein Instrument eine Einheit, die in einer Klangschrift als Einheit verwendet wird, die mehrere Samples kombiniert, und eine Voreinstellung ist eine Einheit, die von Benutzern verwendet werden kann, indem mehrere Instrumente kombiniert werden. Daher werden wir dieses Mal nur voreingestellte Unterblöcke verwenden.

Beachten Sie, dass Unterblöcke als Array von Strukturen gespeichert werden und der Wert am Ende ein spezieller Wert ist, der das Ende angibt. Die Größe ist auch ein ganzzahliges Vielfaches von sizeof (Struktur).

phdr sub-chunk

Der phdr-Unterblock enthält Header-Informationen (voreingestellter Instrumentenname, Bank, voreingestellte Nummer usw.).

struct phdr {
  char achPresetName[20];  //Voreingestellter Name null Terminierung ascii
  WORD wPreset;  //Voreingestellte Nummer
  WORD wBank;  //Banknummer 0~127 für Musikinstrumente 128 für Schlagzeug
  WORD wPresetBagNdx;  //Index am Anfang von pbag
  DWORD dwLibrary; //Reservierung 0
  DWORD dwGenre; //Reservierung 0
  DWORD dwMorphology; //Reservierung 0
}

Beachten Sie, dass wPresetBagNdx ab dem Beginn von phdr in der Reihenfolge erhöht werden muss.

Anfangs habe ich diese Spezifikation übersehen und dachte, dass es in Ordnung wäre, nur phdr neu zu schreiben und unnötige zu löschen, und als Ergebnis der Implementierung wurde ein anderer Sound zu hören. Die Subchunks pbag, pmod und pgen müssen ebenfalls bearbeitet werden, um diese Spezifikation zu erfüllen.

Der Wert des Endes (EOP) von phdr ist wie folgt.

Variablennamen Wert
achPresetName EOP
wPreset 0
wBank 0
wPresetBagNdx Index am Ende von pbag
dwLibrary 0
dwGenre 0
dwMorphology 0

pbag sub-chunk

Der pbag-Subchunk enthält Informationen, die angeben, welche Modulation (pmod) und welcher Generator (pgen) in der Voreinstellung verwendet werden sollen. Die Zuordnung zwischen einem Preset und einem Pbag erfolgt von dem Pbag, auf den wPresetBagNdx eines Presets zeigt, zum Pbag von wPresetBagNdx-1 des nächsten Presets. (Daher ist es möglich, mehrere Pbags einem Preset zuzuordnen.)

struct pbag {
  WORD wGenNdx;  //Index am Anfang von pgen
  WORD wModNdx; //Index am Anfang von pmod
}

Wie phdr müssen wGenNdx und wModNdx vom Anfang des Pbags an inkrementiert werden.

Der Wert am Ende von pbag ist wie folgt.

Variablennamen Wert
wGenNdx Index am Ende von pgen
wModNdx Index am Ende von pmod

pgen sub-chunk

Der pgen-Unterblock speichert Parameterinformationen (Generatoren) wie Instrumente, Volumes und Filter, die Voreinstellungen zugeordnet sind.

Der Inhalt liegt im Schlüsselwertformat der Parametertypen und -werte vor.

struct pgen {
  WORD sfGenOper; //Parametertyp
  WORD genAmount;  //Parameterwert
}

Beachten Sie, dass genAmount je nach Parametertyp zwei Byte-, Kurz- oder Worttypwerte enthält. (Die Größe ist auf Wort festgelegt.)

Der Wert am Ende von pbag ist wie folgt.

Variablennamen Wert
sfGenOper 0
genAmount 0

pmod Sub-Chunk

Der pmod-Unterblock enthält Informationen, die angeben, wie sich der Klang aufgrund dynamischer Parameter wie Änderungen und Geschwindigkeiten der MIDI-Steuerung ändert (Lautstärke ändert, Filter).

struct pmod {
  WORD sfModSrcOper; //Parametertyp der Modulationsquelle(CC, Geschwindigkeit usw.
  WORD sfModDestOper; //Arten von Parametern zu betreiben(Volumen, Filterstärke usw.)
  SHORT modAmount; //Betriebsmenge
  WORD sfModAmtSrcOper; //Arten von Modulationsquellenparametern, die den Umfang der Modulationsmanipulation ändern
  WORD sfModTransOper; //Konvertieren Sie den eingegebenen Operationsbetrag(Linear, gebogen)
}

Der Wert am Ende von pmod ist wie folgt.

Variablennamen Wert
sfModSrcOper 0
sfModDestOper 0
modAmount 0
sfModAmtSrcOper 0
sfModTransOper 0

Sub-Chunk-Beziehung

image.png

Wenn man die Beziehung zwischen den einzelnen Unterblöcken betrachtet, sieht es so aus.

In dem Beispiel dieser Figur ist beispielsweise die Voreinstellung 0 mit bag0 und bag1 verknüpft, bag0 ist mit gen0, gen1 und mod0 verknüpft, und bag1 ist mit gen2 mit mod1 und mod2 verknüpft, sodass der in der Voreinstellung verwendete Generator gen0 ~ ist Das Bild von Gen2 und Modulation ist mod0 ~ mod2.

(Es ist möglicherweise nicht korrekt, da es die Spezifikationen nicht liest, aber es scheint, dass der Generator und die Modulation mit jeder Tasche verbunden sind und ein Geräusch erzeugen, aber Sie müssen sich nicht zu viele Sorgen machen, so weit Sie die Datei berühren können.)

Sound Font Parser

Quellcode: https://github.com/mmitti/sf2conv/blob/master/riff.py

Ich habe ein Skript mit Python und dem Strukturmodul erstellt, das die Struktur von RIFF- und Sound-Schriftarten (teilweise) analysieren kann.

Unterstützt das Lesen und Schreiben von RIFF-Chunks, LIST-Chunks, Phdr-, Pbag-, Pmod- und Pgen-Sub-Chunks. Da die anderen Blöcke nicht bearbeitet werden, wird der gelesene so geschrieben, wie er ist.

Beim Löschen von phdr müssen die entsprechenden für pbag, pmod und pgen gelöscht werden, damit der Aktualisierungsvorgang zum Zeitpunkt des Schreibens ausgeführt wird.

(Ich habe es während der Wartezeit der Automobilschule in den Sommerferien implementiert, aber jetzt ist es schmutzig. RiffRoot oder Element

Ein Programm, das Soundschriften abbildet

Quellcode: https://github.com/mmitti/sf2conv/blob/master/main.py

Ich habe ein Skript erstellt, das die Sound-Schriftart mit dem obigen Riff-Parser (oder besser gesagt dem Sound-Font-Parser) konvertiert und die Tone Map von Music Studio Producer und die Einstellungsdatei von Virtual MIDI Synth ausspuckt.

Schreiben Sie einfach die in die JSON-Datei einzugebenden Sound-Fonts, die auszuschließenden Töne, die Ersetzungsregeln für die Töne, schreiben Sie die Sound-Font-Datei damit neu und spucken Sie die Töne, Bänke und Programmnummern in die Tones-Map aus. Es ist ein Skript.

Es gibt Sounds mit seltsamen Namen (wie ------) und Soundfonts, in denen Blasinstrumentensysteme Klavierprogrammnummern zugewiesen sind, und infolge der Erhöhung der einstellbaren Regeln hat sich die Anzahl der Einstellungselemente erhöht. Sobald die Einstellungsdatei geschrieben ist, werden die Töne jedoch den leeren Teilen zugewiesen und der DAW-Tondiste hinzugefügt, wodurch das Hinzufügen neuer Sound-Schriftarten erleichtert wird.

abschließend

Dieses Mal musste ich, da die DTM-Umgebung beschädigt war, in die Soundschrift schauen, was mein Verständnis ein wenig vertiefte. Da das Hinzufügen von Sound-Schriftarten mit dem Skript einfacher geworden ist, habe ich sinfon eingeführt, das ich sofort verwenden wollte, und einen Song eingegeben.

Nachdem das von mir erstellte FPGA-USB-MIDI-Gerät fertiggestellt ist, möchte ich eine MIDI-Soundquelle erstellen, die Sound-Schriftarten liest, damit ich bald nach Sound-Schriftarten suchen und darüber schreiben kann.

Wir sehen uns wieder

Recommended Posts

Sound Font Mapping Problem
Wahrscheinlichkeitsproblem