سؤال

لا بد لي من تقليل التعمق في إشارة الصوت الرقمية من 24 إلى 16 بت.

إن أخذ 16 بت فقط (أي اقتطاع) لكل عينة يعادل إجراء حساب نسبي (Out = في * 0xffff / 0xffffff)؟

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

المحلول

أفترض أنك تعني (in * 0xFFFF) / 0xFFFFFF, ، في هذه الحالة ، نعم.

نصائح أخرى

ستحصل على نتائج سبر أفضل عن طريق إضافة إشارة ضوضاء مصنوعة بعناية إلى الإشارة الأصلية ، أسفل عتبة المقتطع مباشرة ، قبل اقتطاع (AKA Dithering).

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

إذا لم تكن بحاجة إلى Full on Fidelity of Pow-R ، فيمكنك ببساطة إنشاء بعض الضوضاء في السعة المنخفضة إلى حد ما وامزجها في الإشارة. ستجد هذا الأقنعة بعض تأثيرات القياس.

x * 0xffff / 0xffffff أكثر من اللازم ، ولكن ليس بطريقة جيدة إذا تم توقيع عيناتك - وربما لا تكون بطريقة جيدة بشكل عام.

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

إذا تم توقيع العينات ، فستكون قيم الذروة الإيجابية 0x7FFF و 0x7FFFFF ، في حين أن القيم السلبية الذروة ستكون -0x8000 و -0x800000. مشكلتك الأولى هي تحديد ما إذا كان +1 يساوي 0x7FFF ، أو -1 يساوي -0x8000. إذا اخترت هذا الأخير ، فهذه عملية تحول بسيطة. إذا حاولت أن يكون لديك كلاهما ، فإن الصفر يتوقف عن الصفر.

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

إذا كنت ترغب في التوسع وفقًا لقيمة الذروة الإيجابية ، فإن النموذج الصحيح سيكون:

out = rint((float)in * 0x7fff / 0x7fffff);

إذا كنت تصطاد بعض الشيء ، فيمكنك أن تجد طريقة فعالة للقيام بذلك مع حساب عدد صحيح وليس تقسيم.

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

يفضل معظم الناس:

out = (in + 128) >> 8;
if (out > 0x7fff) out = 0x7fff;

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

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

يمكن لـ C pedants أن يكسب ثقوبًا في الافتراضات حول سلوك التحول الأيمن والانقسام ، لكنني أطل على تلك الموضحة من أجل الوضوح.

ومع ذلك ، كما أشار الآخرون ، يجب ألا تقلل عمقًا من عمق الصوت دون التغلب ، وتشكيل الضوضاء بشكل مثالي. TPDF Dither هو كما يلي:

out = (in + (rand() & 255) - (rand() & 255)) >> 8;
if (out < -0x8000) out = -0x8000;
if (out > 0x7fff) out = 0x7fff;

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

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