تقنية

عينات WAV الستيريو: لماذا لا تكفي صحة عدد الإطارات؟

بطاقات أزواجنا الستة مع أربع خانات بايت لكل زوج؛ أول ثلاث بطاقات مظللة وتمثل اثني عشر بايتا.
ستة أزواج مؤلفة وبايتاتها الفعلية؛ الصف العلوي هو أول ثلاثة إطارات.

في PCM الستيريو ذي16 بت تتتابع عينة اليسار ثم اليمين، ولكل عينة بايتان. [1]

الخلاصة السريعة

  • أنشأنا ثلاثة ملفات، لكل واحد قناتان وستة إطارات وحمولة من 24 بايتا.
  • أعاد paired أزواجنا المقصودة، بينما جمع planar قيما متجاورة من القائمة الخطأ.
  • احتفظ swapped بالقيمتين في كل إطار مع تبادل اليسار واليمين.
  • أعادت قراءة أول ثلاثة إطارات 12 بايتا من كل ملف، رغم اختلاف محتواها.
  • اختبارنا يقارن أرقاما وبايتات محلية؛ لم نشغل الملفات صوتيا أو نقيم جودتها السمعية.

ثبت الأزواج التي تقصدها

اخترنا لليسار L = [100,−40,300,700,−200,50]، ولليمين R = [900,20,−100,70,10,−300]. كل موضع في القائمتين يشكل زوجا مقصودا في تجربتنا: الأول (100,900)، والثاني (−40,20)، وهكذا. ليست القيم تسجيلا لآلة أو صوت بشري؛ ألفناها كي يسهل تمييز كل انتقال بين القناتين.

داخل عينة 16 بت يأتي البايت الأقل أهمية أولا. [1]

الزوج الأول عندنا ينتج 64 00 84 03: القيمة 100 كتبت 64 00، ثم كتبت 900 بالشكل 84 03. في الزوج الثاني أعادت قراءة D8 FF العدد −40، لا 65496؛ اخترنا في البرنامج تمثيلا موقعا عند الحزم والفك. تعرض البطاقات بايتات الملف الفعلي بصيغة ست عشرية.

اكتب ثلاثة ترتيبات مقصودة

شغل البرنامج في مجلد لا يحتوي wav-case. استخدمنا Python 3.12.14 ووحدتيه wave وstruct، دون مكتبات إضافية. القيم الاثنتا عشرة هي نفسها في الفروع الثلاثة، لكننا نغير ترتيبها قبل الكتابة. يفتح كل ناتج من القرص بعد إغلاقه، ثم يطبع حقوله والأطوال والأزواج.

import struct,wave
from pathlib import Path
L=[100,-40,300,700,-200,50]
R=[900,20,-100,70,10,-300]
out=Path("wav-case");out.mkdir()
cases={"paired":[v for pair in zip(L,R) for v in pair],
    "planar":L+R,"swapped":[v for pair in zip(R,L) for v in pair]}
for name,values in cases.items():
    path=str(out/(name+".wav"))
    with wave.open(path,"wb") as w:
        w.setnchannels(2);w.setsampwidth(2);w.setframerate(8000)
        w.writeframes(struct.pack("<12h",*values))
    with wave.open(path,"rb") as w:
        first=w.readframes(3);w.rewind();raw=w.readframes(6)
        params=w.getparams()
    pairs=list(struct.iter_unpack("<hh",raw))
    print(name,params,len(first),len(raw),pairs)
[1] [2]

تعيد readframes بايتات الإطارات، وتضبط دوال الكتابة عدد القنوات وعرض العينة ومعدلها. [2]

في النتائج الثلاث قرأنا قناتين، وعرض عينة 2 بايت، ومعدل 8000، وعدد إطارات 6، ونوع ضغط NONE. كان طول الحمولة 24 في كل مرة. القسمة 24 ÷ (2 × 2) = 6 تعيد العدد الذي سجلناه، لكنها لا تراجع ترتيب القيم داخله.

قارن الأزواج لا العدد وحده

الفرع paired يأخذ قيمة من L ثم المقابلة لها من R. لهذا جاء الناتج كما قصدنا. أما planar فكتب عناصر L الستة أولا ثم عناصر R الستة. عند تجميع الناتج إلى أزواج، صار الأول (100,−40)، والثاني (300,700)؛ لم يزد عدد الإطارات ولم ينقص.

الفرع swapped حافظ على تجاور القيمتين المقصودتين، لكنه عكس موضعيهما. جاء الأول (900,100)، والثاني (20,−40). الاختبار الذي يكتفي بجمع طرفي كل زوج سيمر في هذا الفرع؛ أما المقارنة المرتبة مع zip(L,R) فتفشل فيه. لذلك احتفظنا باتجاه الزوج في جدول المراجعة.

ستة صفوف تقارن الأزواج الصحيحة والمجمعة والمتبادلة؛ تتفق أعداد الإطارات وتختلف القيم في المواضع.
كل عمود ناتج ملف فعلي؛ نقرأ الزوج داخل الأقواس بالترتيب L ثم R.

راجع القراءة الجزئية والبايتات

طلبنا أولا readframes(3)، فاستلمنا 12 بايتا في الملفات الثلاثة. ثم أعدنا المؤشر إلى البداية وطلبنا الإطارات الستة للمقارنة الكاملة. أول حمولة جزئية في paired كانت 64 00 84 03 D8 FF 14 00 2C 01 9C FF. وهي البطاقات الثلاث الأولى في الرسم، وليست ست قيم متتابعة لقناة واحدة.

للتأكد من القيم، أعدنا قراءة حمولة كل ملف مستقلا عن قائمة القيم المستخدمة في الكتابة. فككنا كل زوج بايتات كعدد موقع، ثم جمعنا الأعداد اثنين اثنين. طابقت هذه القراءة نتائج wave الثلاث، وفشل فرعا planar وswapped في مساواة قائمة أزواجنا المقصودة. هذان ضابطان للترتيب في التجربة، لا ملفان تعذر فتحهما.

حدد ما أثبته الاختبار

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

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

المراجع

  1. Microsoft: Devices and Data Types
  2. Python 3.12: wave
أُعد المثال محليا في13 أكتوبر2026.

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