هندسة تنسيق عكسي ثنائية باستخدام ملفات Korg SNG كمثال. الجزء 2



في مقالة سابقة ، وصفت خط الاستنتاج عند تحليل تنسيق بيانات ثنائي غير معروف. باستخدام محرر Hex Synalaze It! ، أوضحت كيف يمكنك تحليل رأس ملف ثنائي وتسليط الضوء على كتل البيانات الرئيسية. نظرًا لأنه في حالة تنسيق SNG ، تشكل هذه الكتل بنية هرمية ، تمكنت من استخدام العودية في القواعد لبناء عرض الشجرة تلقائيًا في نموذج قابل للقراءة من قبل الإنسان.

في هذه المقالة ، سوف أصف منهجًا مشابهًا استخدمته لتحليل بيانات الموسيقى مباشرةً. باستخدام الميزات المضمنة لمحرر Hex ، سوف أقوم بإنشاء نموذج أولي لمحول البيانات إلى تنسيق Midi الشائع والبسيط. سيتعين علينا مواجهة عدد من المزالق والألغاز حول المهمة التي تبدو بسيطة لتحويل عينات الوقت. أخيرًا ، سأشرح كيف يمكنك استخدام النتائج التي تم الحصول عليها وقواعد الملف الثنائي لإنشاء جزء من التعليمات البرمجية للمحول المستقبلي.

تحليل بيانات الموسيقى


لذا ، فقد حان الوقت لمعرفة كيفية تخزين بيانات الموسيقى في ملفات .SNG. في جزء منه ، ذكرت هذا في مقال سابق. تنص وثائق المزج على أنه يمكن أن يحتوي ملف SNG على ما يصل إلى 128 "أغنية" ، كل منها يتكون من 16 مسارًا ومسارًا رئيسيًا واحدًا (لتسجيل الأحداث العالمية وتغيير التأثيرات الرئيسية). على عكس تنسيق Midi ، حيث تتبع الأحداث الموسيقية بعضها البعض مع دلتا وقت محدد ، فإن تنسيق SNG يحتوي على مقاييس موسيقية.

المقياس هو نوع من الحاوية لسلسلة من الملاحظات. يشار إلى بعد البعد في التدوين الموسيقي. على سبيل المثال ، 4/4 - يعني أن المقياس يحتوي على 4 دقات ، كل منها يساوي في مدة ربع سنوية. ببساطة ، سيحتوي هذا الإجراء على أربع أوراق ربع ، أو 2 ملاحظة نصفية ، أو 8 أثمان.

وإليك كيف يبدو في التدوين الموسيقي


يتم استخدام المقاييس الموجودة في ملف SNG لتحرير المقاطع في منظم التسلسل المدمج. باستخدام القائمة ، يمكنك حذف ، إضافة وتكرار التدابير في أي مكان في المسار. يمكنك أيضًا حلقة الدورات أو تغيير بعدها. أخيرًا ، يمكنك ببساطة بدء تسجيل مقطوعة من أي إجراء.

دعونا نحاول أن نرى كيف يتم تخزين كل هذا في ملف ثنائي. الحاوية الشائعة لـ "الأغاني" هي كتلة SGS1. يتم تخزين البيانات لكل أغنية في كتل SDT1:



تقوم كتل SPR1 و BMT1 بتخزين الإعدادات العامة للأغنية (الإيقاع ، إعدادات المسرع) وإعدادات المقطوعات الفردية (التصحيحات ، التأثيرات ، إعدادات arpeggiator ، إلخ). نحن مهتمون بلوك TRK1 - إنه يحتوي على أحداث موسيقية. ولكن عليك أن تنزل أكثر من مستويات التسلسل الهرمي - لمنع MTK1



أخيرًا ، وجدنا مساراتنا - هذه كتل MTE1. دعونا نحاول تسجيل مسار فارغ قصير المدة على المزج وطول فترة زمنية أطول - لفهم كيفية تخزين المعلومات حول المقاييس في النموذج الثنائي.



يبدو أن التدابير يتم تخزينها على أنها هياكل ثمانية بايت. أضف بضع ملاحظات:



لذلك ، يمكننا أن نفترض أن جميع الأحداث يتم تخزينها في نفس النموذج. تحتوي بداية كتلة MTE على معلومات غير معروفة ، ثم ينتقل تسلسل بنيات ثمانية بايت إلى النهاية. افتح محرر القواعد وقم بإنشاء بنية حدث بحجم 8 بايت.

أضف هيكل mte1Chunk الذي يرث childChunk ووضع رابطًا للحدث في بنية البيانات . نشير إلى أن هذا الحدث يمكن أن يتكرر عدد غير محدود من المرات. بعد ذلك ، من خلال التجارب ، اكتشفنا حجم وغرض عدة بايت قبل بدء دفق أحداث المسار. حصلت على ما يلي:



في بداية الكتلة MTE1 ، يتم تخزين عدد أحداث المسار ، ورقمه ، ويفترض أن يكون بعد الحدث. بعد تطبيق القواعد ، بدأت الكتلة تبدو كما يلي:



دعنا ننتقل إلى تدفق الأحداث. بعد تحليل عدة ملفات بتسلسلات مختلفة من الملاحظات ، تظهر الصورة التالية:
#اكتبالتمثيل الثنائي
1فاز 101 00 00 ...
2ملاحظة09 00 3C ...
3ملاحظة09 00 3C ...
4ملاحظة09 00 3C ...
5Beat201 C3 90 ...
6ملاحظة09 00 3C ...
7نهاية المسار03 88 70 ...

يبدو أن البايت الأول يشفر نوع الحدث. إضافة حقل كتابة إلى بنية الحدث . دعونا إنشاء اثنين من الهياكل الأخرى ورث الحدث : التدبير والملاحظة . نشير إلى القيم الثابتة المقابلة لكل منها. وأخيرًا ، أضف روابط إلى هذه الهياكل في بيانات كتلة mte1Chunk .



تطبيق التغييرات:



حسنا ، لقد حققنا تقدما جيدا. يبقى أن نفهم كيف يتم ترميز ارتفاع وقوة الملاحظة ، وكذلك التحول الزمني لكل حدث بالنسبة إلى الأحداث الأخرى. دعونا نحاول مرة أخرى مقارنة ملفاتنا بنتيجة التصدير إلى midi ، التي تتم من خلال قائمة synthesizer. هذه المرة نحن مهتمون بالتحديد بأحداث النقر على الملاحظات.



نفس الأحداث في ملف SNG


! ممتاز يبدو أن درجة الصوت وضغط الملاحظات يتم تشفيرها بنفس الطريقة تمامًا كما في تنسيق midi مع بضع بايت. أضف الحقول المناسبة إلى القواعد.

لسوء الحظ ، الأمور ليست بهذه البساطة مع تحول مؤقت.

نحن نتعامل مع المدة والدلتا


في تنسيق midi ، تكون الأحداث NoteOn و NoteOff منفصلة. يتم تحديد مدة الملاحظة بواسطة وقت دلتا بين هذه الأحداث. في حالة تنسيق SNG ، حيث لا يوجد تماثل لحدث NoteOff ، يجب تخزين قيم دلتا المدة والوقت في بنية واحدة.

لفهم كيف يتم تخزينها ، قمت بتسجيل العديد من تسلسل الملاحظات من فترات مختلفة على المزج.



من الواضح أن البيانات التي نحتاجها موجودة في آخر 4 بايتات من بنية الحدث. لا يكون الانتظام مرئيًا بالعين المجردة ، لذلك نختار البايتات التي تهمنا في المحرر ونستخدم أداة لوحة البيانات.

النص المخفي


على ما يبدو ، يتم تشفير كل من مدة الملاحظة وتحول الوقت بواسطة زوج من البايتات (UInt16). في هذه الحالة ، يكون ترتيب البايت عكسًا - Little Endian. بعد مقارنة كمية كافية من البيانات ، اكتشفت أن دلتا الوقت هنا لا يتم احتسابها من الحدث السابق كما هو الحال في midi ، ولكن من بداية الساعة. إذا انتهت الملاحظة في المقياس التالي ، فسيكون طوله في المقياس الحالي هو 0x7fff ، ويتم تكراره في المقياس التالي بنفس دلتا 0x7fff والمدة المحسوبة بالنسبة لبداية التدبير الجديد. في المقابل ، إذا كانت الملاحظة تبدو عدة مقاييس ، فستكون مدتها وحجمها في كل واحدة وسيطة 0x7fff.

دائرة صغيرة

يتم حساب الوحدات الزمنية دلتا / المدة في الخلايا. تبدو الملاحظة 1 عادية ، وتواصل الملاحظة 2 الصوت في المقاييس الثانية والثالثة.

في رأيي ، كل هذا يبدو غريب الأطوار. من ناحية أخرى ، في التدوين الموسيقي ، يشار إلى السبر المستمر لعدة تدابير بطريقة مماثلة بواسطة legato.

في أي "الببغاوات" لدينا مدة؟ مثل ميدي ، يتم استخدام التشنجات اللاإرادية هنا. من الوثائق ، من المعروف أن مدة المشاركة الواحدة هي 480 علامة. بإيقاع 100 نبضة في الدقيقة وبعد 4/4 ، تكون مدة النغمة ربع السنوية (60/100) = 0.6 ثانية. وفقًا لذلك ، تكون مدة علامة التجزئة 0.6 / 480 = 0.00125 ثانية. ستدوم 4/4 القياسية 4 * 480 = 1920 القراد أو 2.4 ثانية بمعدل 100 نبضة في الدقيقة.

كل هذا سيكون مفيدًا لنا في المستقبل. في غضون ذلك ، أضف المدة والدلتا إلى هيكل الملاحظات لدينا. لاحظ أيضًا وجود حقل في بنية اللباقة يخزن عدد الأحداث. يحتوي الحقل الآخر على الرقم التسلسلي للمقياس - قم بإضافته إلى بنية القياس .



تحويل النموذج الأولي


الآن لدينا معلومات كافية لمحاولة تحويل البيانات. يسمح لك محرر Hex Synalaze It في الإصدار المحترف بكتابة البرامج النصية في python أو lua. عند إنشاء برنامج نصي ، يجب أن تقرر ما الذي نريد العمل به: باستخدام القواعد النحوية نفسها ، مع الملفات الفردية على القرص أو معالجة البيانات التي تم تحليلها بطريقة أو بأخرى. لسوء الحظ ، كل من القوالب لديه بعض القيود. يوفر البرنامج عددًا من الفئات وطرق العمل ، ولكن لا يمكن الوصول إليها جميعًا من جميع القوالب. ربما يكون هذا خطأ في الوثائق ، لكنني لم أجد كيف يمكنك تحميل القواعد لقائمة من الملفات وتحليلها واستخدام الهياكل الناتجة لتصدير البيانات.

لذلك ، سنقوم بإنشاء برنامج نصي للعمل مع نتيجة تحليل الملف الحالي. ينفذ هذا القالب ثلاث طرق: init ، إنهاء ، و processResult. يتم استدعاء الأخير تلقائيًا ويمر بشكل متكرر من خلال جميع الهياكل والبيانات المستلمة أثناء التحليل.

لكتابة البيانات المحولة في midi ، نستخدم مجموعة أدوات Python MIDI (https://github.com/vishnubob/python-midi). نظرًا لأننا ننفذ "إثبات المفهوم" ، فلن نقوم بتحويل فترات المذكرة والدلتا. بدلا من ذلك ، وضعنا القيم الثابتة. يتم تجاهل الملاحظات التي مدتها 0x7fff أو مع دلتا مماثلة في الوقت الحالي.

إمكانيات محرر النصوص المضمنة محدودة للغاية ، لذلك يجب وضع كل الشفرة في ملف واحد.

gist.github.com/bkotov/71d7dfafebfe775616c4bd17d6ddfe7b

لذلك ، دعونا نحاول تحويل الملف والاستماع إلى ما حصلنا عليه


هم ... واتضح للاهتمام جدا. أول ما حدث لي عندما حاولت صياغة ما بدا عليه هو الموسيقى بدون بنية. سأحاول إعطاء تعريف:

الموسيقى غير المهيكلة - قطعة من الموسيقى ذات بنية منخفضة ، مبنية على الانسجام. ملاحظة يتم إلغاء الفواصل الزمنية والفترات الفاصلة بين الملاحظات أو تخفيضها إلى نفس القيم.

نوع من الضوضاء المتناغمة. فليكن لؤلؤي (عن طريق القياس باللون الأبيض والأزرق والأحمر والوردي ، وما إلى ذلك) ، يبدو أن أحداً لم يأخذ هذه المجموعة.

ربما يجب أن نحاول تدريب شبكة عصبية على بياناتي ، وربما تكون النتيجة مثيرة للاهتمام.

مهمة الاحماء العقل


كل هذا رائع ، لكن المشكلة الرئيسية لم تحل بعد. نحتاج إلى تحويل فترات الملاحظة إلى أحداث NoteOff ، وإزاحة وقت الحدث بالنسبة لبداية التدبير إلى دلتا زمنية بين الأحداث المجاورة. سأحاول صياغة شروط المشكلة بشكل أكثر رسمية.

التحدي
:
1
1
2
3
...
N
2
...
N
1
...



: 1
: 1920
: Int
: Int


: 9
: 0-127
: 0-127
: 0-1920 0xFF
: 0-1920 0xFF

, , 0xFF, =0xFF . , . = = 0xFF.

.

midi. :

:
: 9
: 0-127
: 0-127
: Int

:
: 8
: 0-127
: 0-127
: Int


المهمة مبسطة قليلاً. في ملف SNG حقيقي ، يمكن أن يكون لكل قياس بعد مختلف. بالإضافة إلى أحداث On / Off ، ستحدث أحداث أخرى أيضًا في الدفق ، على سبيل المثال ، الضغط على دواسة الاستدامة أو تغيير الملعب باستخدام pitchBend.

سأقدم حل لهذه المشكلة في المقالة التالية (إذا كان هناك حل).

النتائج الحالية


نظرًا لأن مقياس البرنامج النصي لا يتعدى عدد الملفات بشكل تعسفي ، فقد قررت كتابة محول وحدة التحكم في Swift. إذا كتبت محولًا ثنائي الاتجاه ، فستكون بنى القواعد النحوية مفيدة لي في التعليمات البرمجية. يمكنك تصديرها إلى بنى C أو أي لغة أخرى باستخدام نفس وظيفة البرمجة النصية المدمجة في Synalize It! يتم إنشاء ملف به مثال على هذا التصدير تلقائيًا عند تحديد قالب نحوي.



في الوقت الحالي ، يكتمل المحول بنسبة 99٪ (بالشكل الذي يناسبني من حيث الأداء الوظيفي). أخطط لوضع الشفرة والقواعد على جيثب.

مثال ، الذي بدأ كل شيء ، يمكنك الاستماع هنا .

كيف تبدو هذه القطعة جاهزة.

Source: https://habr.com/ru/post/ar442740/


All Articles