سؤال

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

لقد قمت حتى الآن بالتحقق من استخدام تحويل فورييه السريع للكشف عن درجة الصوت، وقد أظهر عدد من الاختبارات في كل من MATLAB وبرامج اختبار Java الخاصة بي أنه سريع ودقيق بما يكفي لتلبية احتياجاتي.عنصر آخر من المهمة التي يجب معالجتها هو عرض بيانات MIDI المنتجة في شكل نوتة موسيقية، لكن هذا شيء لست مهتمًا به الآن.

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

هل كانت مفيدة؟

المحلول

فيما يلي رسم يوضح نهج العتبة لملاحظة اكتشاف البداية:

alt text

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

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

الحل الأبسط هو استخدام الضغط المسمى بشكل غير بديهي إلى حد ما (ليس ضغط MP3 - هذا شيء آخر تمامًا) على ملف الموجة الخاص بك أولاً.يؤدي الضغط بشكل أساسي إلى تسوية الارتفاعات في بياناتك الصوتية ثم تضخيم كل شيء بحيث يقترب المزيد من الصوت من القيم القصوى.سيبدو التأثير على العينة المذكورة أعلاه كما يلي (مما يوضح سبب عدم معنى اسم "الضغط" - في الأجهزة الصوتية يُسمى عادةً "جهارة الصوت"):

alt text

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

من حيث الترميز، فإن ملف WAV الذي يتم تحميله في الذاكرة هو في الأساس مجرد مجموعة من الأعداد الصحيحة ثنائية البايت، حيث يمثل 0 عدم وجود إشارة ويمثل 32,767 و-32,768 القمم.في أبسط أشكالها، ستبدأ خوارزمية الكشف عن العتبة من العينة الأولى وتقرأ خلال المصفوفة حتى تجد قيمة أكبر من العتبة.

short threshold = 10000;
for (int i = 0; i < samples.Length; i++)
{
    if ((short)Math.Abs(samples[i]) > threshold) 
    {
        // here is one note onset point
    }
}

من الناحية العملية، يعمل هذا بشكل رهيب، نظرًا لأن الصوت العادي يحتوي على جميع أنواع الارتفاعات العابرة فوق عتبة معينة.أحد الحلول هو استخدام متوسط ​​قوة الإشارة الجارية (أي.لا تضع علامة على البداية حتى يصبح متوسط ​​آخر عدد من العينات أعلى من العتبة).

short threshold = 10000;
int window_length = 100;
int running_total = 0;
// tally up the first window_length samples
for (int i = 0; i < window_length; i++)
{
    running_total += samples[i];
}
// calculate moving average
for (int i = window_length; i < samples.Length; i++)
{
    // remove oldest sample and add current
    running_total -= samples[i - window_length];
    running_total += samples[i];
    short moving_average = running_total / window_length;
    if (moving_average > threshold)
    {
        // here is one note onset point 
        int onset_point = i - (window_length / 2);
    }
}

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

تحديث:يوضح هذا الرسم تفاصيل اكتشاف الملاحظة التي أهملتها، وتحديدًا اكتشاف وقت انتهاء الملاحظة:

alt text

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

بمجرد اكتشاف نقاط البداية والتوقف لكل ملاحظة، يمكنك الآن تحليل كل شريحة من بيانات ملف WAV لتحديد طبقات الصوت.

التحديث 2:لقد قرأت للتو سؤالك المحدث.يعد اكتشاف درجة الصوت من خلال الارتباط التلقائي أسهل بكثير في التنفيذ من تطبيق FFT إذا كنت تكتب كتابًا خاصًا بك من البداية، ولكن إذا كنت قد قمت بالفعل بسحب مكتبة FFT المبنية مسبقًا واستخدمتها، فمن الأفضل استخدامها بالتأكيد .بمجرد تحديد مواضع البداية والتوقف لكل ملاحظة (وتضمين بعض المساحة المتروكة في البداية والنهاية لأجزاء الهجوم والإصدار الفائتة)، يمكنك الآن سحب كل شريحة من البيانات الصوتية وتمريرها إلى وظيفة التحويل السريع (FFT) إلى تحديد الملعب.

إحدى النقاط المهمة هنا هي عدم استخدام شريحة من البيانات الصوتية المضغوطة، بل استخدام شريحة من البيانات الأصلية غير المعدلة.تؤدي عملية الضغط إلى تشويه الصوت وقد تنتج قراءة غير دقيقة لطبقة الصوت.

نقطة أخيرة حول أوقات الهجوم على الملاحظات هي أنها قد تكون مشكلة أقل مما تعتقد.في كثير من الأحيان في الموسيقى، تبدأ الآلة ذات النغمة البطيئة (مثل السِنث الناعم) نغمة أبكر من أداة النغمة الحادة (مثل البيانو) وستبدو كلتا النغمتين كما لو أنهما تبدأان في نفس الوقت.إذا كنت تعزف على الآلات بهذه الطريقة، فإن الخوارزمية التي تستخدمها تلتقط نفس وقت البدء لكلا النوعين من الآلات، وهو أمر جيد من منظور WAV إلى MIDI.

التحديث الأخير (أتمنى):انسَ ما قلته بشأن تضمين بعض عينات الحشوات من جزء الهجوم المبكر لكل ملاحظة - لقد نسيت أن هذه في الواقع فكرة سيئة لاكتشاف طبقة الصوت.تحتوي أجزاء الهجوم في العديد من الآلات (خاصة البيانو وغيره من الآلات الإيقاعية) على انتقالات ليست مضاعفات طبقة الصوت الأساسية، وسوف تميل إلى إفساد اكتشاف طبقة الصوت.أنت في الواقع تريد أن تبدأ كل شريحة بعد الهجوم بقليل لهذا السبب.

أوه، ونوع من المهم: مصطلح "الضغط" هنا لا يشير إلى الضغط بنمط MP3.

التحديث مرة أخرى:إليك وظيفة بسيطة تقوم بالضغط غير الديناميكي:

public void StaticCompress(short[] samples, float param)
{
    for (int i = 0; i < samples.Length; i++)
    {
        int sign = (samples[i] < 0) ? -1 : 1;
        float norm = ABS(samples[i] / 32768); // NOT short.MaxValue
        norm = 1.0 - POW(1.0 - norm, param);
        samples[i] = 32768 * norm * sign;
    }
}

عندما تكون المعلمة = 1.0، لن يكون لهذه الوظيفة أي تأثير على الصوت.القيم المعلمة الأكبر (2.0 جيدة، والتي ستؤدي إلى تربيع الفرق الطبيعي بين كل عينة وقيمة الذروة القصوى) ستنتج المزيد من الضغط وصوتًا أعلى بشكل عام (لكن سيئًا).القيم الأقل من 1.0 ستنتج تأثيرًا توسعيًا.

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

تحديث:فيما يلي إصدار من StaticCompress الذي سيتم تجميعه في C# ويلقي كل شيء بشكل صريح.هذا يعيد النتيجة المتوقعة:

public void StaticCompress(short[] samples, double param)
{
    for (int i = 0; i < samples.Length; i++)
    {
        Compress(ref samples[i], param);
    }
}

public void Compress(ref short orig, double param)
{
    double sign = 1;
    if (orig < 0)
    {
        sign = -1;
    }
    // 32768 is max abs value of a short. best practice is to pre-
    // normalize data or use peak value in place of 32768
    double norm = Math.Abs((double)orig / 32768.0);
    norm = 1.0 - Math.Pow(1.0 - norm, param);
    orig = (short)(32768.0 * norm * sign); // should round before cast,
        // but won't affect note onset detection
}

آسف، درجة معرفتي في Matlab هي 0.إذا قمت بنشر سؤال آخر حول سبب عدم عمل وظيفة Matlab كما هو متوقع، فسيتم الرد عليه (ليس بواسطتي).

نصائح أخرى

ما تريد القيام به غالبا ما يسمى WAV إلى MIDI (جوجل "wav-to-midi").لقد كانت هناك العديد من المحاولات لهذه العملية، وكانت النتائج متفاوتة (لاحظ أن البداية هي إحدى الصعوبات؛من الصعب جدًا التعامل مع تعدد الأصوات).أنصحك بالبدء ببحث شامل عن الحلول الجاهزة، والبدء بالعمل بنفسك فقط إذا لم يكن هناك شيء مقبول.

الجزء الآخر من العملية الذي ستحتاجه هو شيء ما لعرض مخرجات MIDI كنتيجة موسيقية تقليدية، ولكن هناك مليارًا لا يحصى من المنتجات التي تفعل ذلك.

الجواب الآخر هو:نعم، لقد قمت بالكثير من معالجة الإشارات الرقمية (راجع البرنامج الموجود على موقع الويب الخاص بي - إنه برنامج مركب صوتي لا نهائي مكتوب بلغة VB وC)، وأنا مهتم بمساعدتك في حل هذه المشكلة.إن جزء WAV-to-MIDI ليس بهذه الصعوبة من الناحية النظرية، ولكن فقط جعله يعمل بشكل موثوق في الممارسة العملية هو أمر صعب.بداية الملاحظة هي مجرد تحديد عتبة - يمكن تعديل الأخطاء بسهولة للأمام أو للخلف في الوقت المناسب للتعويض عن اختلافات هجوم الملاحظة.يعد اكتشاف درجة الصوت أسهل بكثير في التسجيل منه في الوقت الفعلي، ويتضمن فقط تنفيذ روتين الارتباط التلقائي.

ويجب أن ننظر في MIRToolbox - هو مكتوب لمطلب، ويحتوي على كاشف بداية بنيت في - أنه يعمل بشكل جيد جدا. شفرة المصدر هو GPL'd، حتى تتمكن من تنفيذ خوارزمية في أي لغة تعمل لك. ما هي اللغة رمز الإنتاج ذهابك للاستخدام؟

وتتركز هذه المكتبة حول وضع العلامات الصوت:

aubio

<اقتباس فقرة>   

وaubio هي مكتبة لوصفها الصوت. وتشمل معالمه تقسيم ملف الصوت قبل كل من هجماته، وأداء كشف الملعب، والتنصت على إيقاع وإنتاج تيارات ميدي من الصوت الحي. وaubio اسم يأتي من 'الصوت' مع الخطأ المطبعي: من المرجح أن تكون وجدت في نتائج عدة أخطاء النسخ أيضا

ولقد كان حظا سعيدا معها للكشف عن ظهور وكشف الملعب. انها في ج، ولكن هناك جرعة كبيرة / مغلفة الثعبان.

وأيضا، صاحب المكتبة لديها قوات الدفاع الشعبي من أطروحته على الصفحة، التي لديها معلومات كبيرة وخلفية حول وضع العلامات.

يمكن اكتشاف البداية الصعبة بسهولة في المجال الزمني باستخدام قياس متوسط ​​الطاقة.

المجموع من 0 إلى N (X^2)

افعل ذلك مع أجزاء من الإشارة بأكملها.من المفترض أن ترى قممًا عند حدوث البداية (حجم النافذة متروك لك، واقتراحي هو 50 مللي ثانية أو أكثر).

أوراق واسعة النطاق حول اكتشاف البداية:

للمهندسين المتشددين:

http://www.nyu.edu/classes/bello/MIR_files/2005_BelloEtAl_IEEE_TSALP.pdf

من الأسهل على الشخص العادي أن يفهم:

http://bingweb.binghamton.edu/~ahess2/Onset_Detection_Nov302011.pdf

وقد تتمكن من محاولة لتحويل إشارة الرعايا الى الرسم البياني من السعة مع الزمن. ثم وسيلة لتحديد بداية ثابت هو لحساب تقاطع المماس في نقطة انعطاف من الجهة ارتفاع إشارة مع محور س.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top