"الرب سبحانه وتعالى! يبدو أنني قتلت السيد ماي! ... ولكن كن على هذا النحو ، سنستمر ”(C) J. Clarkson
في هذه المقالة ، سأخبرك بكيفية نقل الفيديو (حسنًا ، فيديو تقريبًا) باستخدام الصوت عبر الماء باستخدام كمبيوتر محمول عادي ، وقطعة من الأسلاك ، ومقبسين 3.5 مم واثنين من مكبرات الصوت بيزو. سأشرح أيضًا لماذا وكيف يعمل ، أخبر قصة مضحكة عن كيفية التوصل إلى هذا. وككرز على كعكة ، يتم إرفاق مقالة على C # مع رموز المصدر بالمقالة بحيث يمكن لكل شخص مهتم تجربتها بأنفسهم ، لأن المعرفة العلمية يمكن التحقق منها ، أليس كذلك؟
إذا أراد القارئ فجأة التعمق أكثر في الموضوعات الصوتية المائية ، أقترح أن تتعرف على منشوراتنا السابقة ، حيث نتحدث عن مشاريعنا بطريقة تكشف عن صعوبات نقل المعلومات عبر الماء:
نظام تحديد المواقع تحت الماء من الصفر في السنةنظام تحديد المواقع العالمي تحت الماء: تابعالتنقل تحت الماء: العثور على الاتجاه - عدم العثور على الاتجاه ، محكوم عليك بالنجاححول تأثير البكتيريا الزرقاء على وظائف الكلام للرئيسبشكل عام ، يجب تعلم حقيقة واحدة بسيطة: لا يمكن نقل الفيديو عبر الماء على أي مسافة كبيرة (حسنا ، على الأقل مئات الأمتار) باستخدام الصوتيات. والنقطة هي نطاق التردد المتاح الضيق للغاية والتفاوت القوي في التوهين للترددات المختلفة مع المسافة. الإيجابيات هي الضوضاء ، الانتشار متعدد المسارات ، الصدى ، التغير في سرعة الصوت في الوسط من الكثافة (أي الضغط ، درجة الحرارة والملوحة) ، تأثير دوبلر ، الذي لا يعمل بالمناسبة تمامًا مثل الاتصالات اللاسلكية.
حدود السرعة لأجهزة مودم السونار الأكثر تقدمًا بعيدة جدًا عن القدرة على إرسال الفيديو. على حد علمي ، ينتمي السجل إلى EvoLogics ويبلغ 62.5 كيلوبت في الثانية مع مسافة قصوى تبلغ 300 متر. علاوة على ذلك ، فإن الكلمات حول استحالة إرسال صوت الفيديو عبر الماء (على مسافات معقولة) تنتمي فقط إلى كونستانتين جورجيفيتش ، مؤسس ومدير EvoLogics.
عندما كنت باحثًا في معهد أبحاث Hydrosvyaz ، ثم فقدت الوعي تمامًا ، كنت أرغب في تحقيق إنجازات كبيرة ،
وانتصارات في الشمال والجنوب ، وتخفيف كبير للتربة (لا ، ما زلت أرغب فيها ، ولكن بعد ذلك لم أكن مثقلًا بالخبرة والمعرفة و كل شيء بدا سحريًا ورائعًا تقريبًا). في فريقنا في ذلك الوقت (جزء مني هو حقيقي) ، غالبًا ما كنا نتخيل بعضًا من مشاريع السونار غير الواقعية ، التي تم نصبها في
مكب النفايات وحاولت استخدام جميع أنواع القطع الأثرية من حضارة قديمة عظيمة على التوالي ، والتي يحاول معهد الأبحاث هذا جزئيًا فهم تاو التواصل بالسونار .
الغمر في تلك الذكريات يثير مشاعر متضاربة في داخلي. ثم لم يبد شيئًا ولا يمكن لأحد أن يوقفنا: لقد أخرجنا آلة طحن صينية من مدير النماذج الأولية للمنتجات ، جمعت الأجسام المعيارية من أنابيب المياه الهولندية Van De Lande ، التي صنعت الشركة المصنعة خطابًا حول هذا الموضوع: "هل راجعت عن طريق الخطأ أي هل تتحمل الأنابيب الضغط الخارجي؟ " قاموا بجمع نماذج اللوح لأموالهم الخاصة في حاويات الإفطار وخرجوا سراً للاختبار لاختبارهم سراً ، وجمعوا تدريبات الجليد والزلاجات للزملاء والأقارب ، وحتى اشتروا قارب PVC الصيني في أوشان. إذا نظرنا إلى الوراء ، أشعر كيف أن قلبي مليء بالرعب والحنين والخوف.
في الإنصاف ، تجدر الإشارة إلى أننا حصلنا طوال الوقت على دعم كبير من بعض قادتنا - في الكلام والفعل ، ونتيجة لذلك تم تقنين جميع حرفنا في الوسواس القهري (وهذا يعني عمل التصميم التجريبي وليس الوسواس القهري) ، والذي كان حتى قدم في صالون البحرية الدولية في عام 2013. نعم ، نعم ، سافرنا إلى الصالون أنابيب المياه الخاصة بنا ،
ورسمنا StDmitirev بيدنا باللون البرتقالي الساطع! ها هم ، في حقائب:

ذات يوم ، قال صديقي وزميلي
StDmitirev ، في وسط محادثة حول الأطياف والأطياف ، الجملة التالية:
"ولكن ، سيكون من الممتع إنشاء مثل هذا النظام: الغواصة تجلس في الغواصة وتنظر إلى الشاشة ، حيث يتحرك الطيف الضوئي بسلاسة ، حيث تتم كتابة الأحرف والأرقام مثل إصبع غواصة أخرى على النافذة الضبابية لغواصة أخرى ."
الجميع ضحك ، طوروا هذا الموضوع ، يبدو أنه حتى في نفس اليوم رسموا وجه مبتسم على الطيف واستمعوا إلى كيف يبدو. أردت حقًا أن أضع هذا في نظرة عملية.
الآن من الصعب التذكر (كان ذلك في عام 2012). كان لدي جهاز كمبيوتر يعمل بكاميرا ويب والعديد من هوائيات التحف الفنية و "تعزيز سونار دلو" خاص (VG-1-P) بالماء. لقد أطلقوا عليه خطوة تصاعدية لأنني عرضت على جميع رؤسائه عمل نماذج مختلفة من المعدات ، مما أدى إلى ترقيتي إلى باحث أول.
لست مقيدًا بأي التزامات ، فقد تم نشر الطريقة نفسها منذ فترة طويلة في المجال العام ، وتم الإبلاغ عن النتائج بشكل متكرر في المؤتمرات.
لذا ، أخبركم بروحًا - كيف تبث فيديو عبر الماء:
كيف تولد اشارة؟
نتذكر أن الفكرة تستند إلى "الرسم على مطياف" ، أي أن الصورة المرسلة هي مطياف الإشارة. لتحويل إشارة من المجال الزمني إلى نطاق التردد والعكس بالعكس ، من المناسب استخدام (تحويل ، على سبيل المثال) تحويل فورييه ، أو بالأحرى ، تحويل فورييه السريع ، للإيجاز ، يسمى FFT أو ، بشكل أكثر شيوعًا ، FFT (تحويل فورييه السريع).
نظرًا لأننا بحاجة إلى تحويل صورة (إطار فيديو) إلى إشارة صوتية يمكن أن تنبعث من بطاقة الصوت لأي جهاز كمبيوتر ، فمن الواضح أننا سنستخدم التحويل العكسي ، IFFT ، لتشكيلها. سوف نبعث صورة في الأعمدة ، وسيتم تشكيل إشارة لعمود واحد كما في الرسم البياني التالي:
=
لنفترض أن حجم نافذة FFT هو N ولدينا صفيف من الحجم N. إذا اعتبرناه طيف الإشارة ، فإن عنصره صفر يتوافق مع التردد الصفري (ثابت) ، والعدد مع مؤشر N-1 يتوافق مع تردد أخذ العينات معدل العينة. من الضروري اختيار أحجام إطارات الصور وحجم نافذة FFT بحيث يشبه الفيديو بطريقة أو بأخرى من ناحية (يستغرق نقل إطار واحد فترة زمنية معقولة) ، ومن ناحية أخرى ، كان نطاق التردد المستخدم مناسبًا من حيث المبدأ وملائمًا للمعدات المتاحة . الآن ، إذا أدخلنا قيم السطوع لعمود الصورة (Frame coloumn) من بعض العد المفضل (من الأسفل إلى الأعلى في الرسم التخطيطي) ، ثم قمنا بإجراء عكس FFT ، عندئذٍ سيتلقى الإخراج إشارة ترميز عمود واحد من الصورة. الآن يبقى لنا أن نشكل الإشارات بالطريقة نفسها للأعمدة المتبقية من الصورة ونرسلها بالتناوب باستخدام بطاقة صوت.
تجدر الإشارة إلى أن FFT عند الإخراج يعطي مجموعة من القيم المعقدة ، لذا فإن إشارتنا هي الجزء الحقيقي. بالطبع ، يتم تقليل الإشارة الناتجة في الأعمدة إلى أعداد صحيحة 16 بت (في هذا النموذج ، عادة ما يتم تخزين إشارة صوتية رقمية) وتطبيعها.
في الواقع ، في بداية الصورة ، أقوم أيضًا بإدخال بعض الأعمدة ذات السطوع الأقصى ، وبعد ذلك على جانب جهاز الاستقبال ، سيحدد ذلك استجابة التردد لمسار جهاز الإرسال والاستقبال (وقناة الإرسال) ، والتي ، عندما تكون مقلوبة وناعمة قليلاً ، ستساعدنا في تحسين الإطار المستلم.
في رأيي ، فإن أسهل طريقة لإثبات جهاز المرسل هي من خلال جزء من الكود ، وهنا هو (طريقة التشفير لفئة Encoder):
public double[] Encode(Bitmap source) { Bitmap frame; if (source.PixelFormat != System.Drawing.Imaging.PixelFormat.Format8bppIndexed) frame = Grayscale.CommonAlgorithms.RMY.Apply(source); else frame = source; if (!frame.Size.Equals(frameSize)) frame = resizer.Apply(frame); double[] samples = new double[fftSize * frameSize.Width]; alglib.complex[] slice = new alglib.complex[fftSize]; double maxSlice; int sampleIndex = 0; int colsCount = frameSize.Width; int startRow = startLine; int endRow = startRow + frameSize.Height; for (int x = 0; x < colsCount; x++) { for (int y = startRow; y < endRow; y++) slice[y].x = (frame.GetPixel(x, frameSize.Height - (y - startRow) - 1).R / 255.0) * short.MaxValue; for (int y = 0; y < fftSize; y++) slice[y].x *= randomizerMask[y]; alglib.fftc1dinv(ref slice); maxSlice = double.MinValue; for (int y = 0; y < slice.Length; y++) if (Math.Abs(slice[y].x) > maxSlice) maxSlice = Math.Abs(slice[y].x); for (int i = 0; i < slice.Length; i++) { samples[sampleIndex] = (short)Math.Round(slice[i].x * short.MaxValue / maxSlice); sampleIndex++; } } return samples; }
بطبيعة الحال ، لا يتظاهر القانون بأي شيء ، وقد كتب في عجلة من أمره لمجرد مظاهرة.
فماذا عن سرعة الإرسال؟
وكيف تقيمها؟ تمكنا (
من الشر وليس من الشر) من الحفاظ على دسيسة لمدة شهرين تقريبًا ، وتمكن بعض كبار رفاقنا وقادةنا من كتابة مجموعة من الورق في أوقات فراغهم ، متسائلين كيف يمكن أن تتحول سرعة النقل المجنونة هذه.
على سبيل المثال ، إذا كان تردد أخذ العينات 96 كيلو هرتز ، وأخذنا حجم نافذة FFT إلى 512 ، فسوف نرسل 120 × 120 بكسل (8 بت لكل بكسل) إلى إدخال جهاز الإرسال ، ثم الوقت المستغرق لإرسال إطار صورة واحد هو:
120 * 512/96000 = 0.64 ثانيةيجب أن يبدو معدل البت كما يلي:
120x120 * 8 / 0.64 = 180،000 بت في الثانية!كان ابن المخرج سعيدًا في ذلك الوقت - نعم ، يمكنك بالفعل استخدام بروتوكولات الإنترنت! هذا انفراج!كما سأوضح أدناه ، من السهل جدًا الوقوع في هذا الاعتقاد الخاطئ. ما هو الخطأ هنا؟ بعد كل شيء ، كل شيء بسيط وأنيق!
في الواقع ، لا ينطبق حساب السرعة على هذه الطريقة ، تمامًا كما هو الحال ، على سبيل المثال ، لا ينطبق على إشارة تلفزيون تمثيلي ، كم عدد البتات لكل بكسل؟ =) وماذا عن أبسط جهاز استقبال للكشف عن؟ =))
طريقة الإرسال الموصوفة هي في الأساس
تناظرية ولا
تنطبق عليها مفاهيم "البت" و "البكسل" - في نفس الصورة ، نظريًا ، لا يمكنك أخذ 8 بت لكل سطوع بكسل ولكن 16 و "السرعة" ستتضاعف تلقائيًا.
حان الوقت لإظهار النتائج الأولى لـ "الاختراق":

تم التقاط الصورة أعلاه من قبلنا في شتاء عام 2012 على نهر Pichuga. كانت مسافة الإرسال 700 متر. نعم ، للأسف ، عزيزي القارئ ، هذا ليس عالي الدقة على الإطلاق ولا يعتمد حتى على CamRip الأكثر مخزية. لا أتذكر من بالفعل ، ولكن شخصًا ما لاحظ بدقة شديدة أن "مقاطع الفيديو" الخاصة بنا تشبه إرسال إشارات للمساعدة من كوكب يحتضر.
ما هو جدير بالملاحظة ، مع امتداد هذا يمكن وصفه بأنه نوع من OFDM - يتم إرسال البيانات على ناقلات فرعية متعامدة ، مما يعني مقاومة جيدة للتداخل النغمي وغيرها من التداخلات الضيقة النطاق - في هذه الحالة ، يتم تشويه "خطوط" فردية للصورة. على العكس من ذلك ، فإن ضوضاء النبض تشوه عمودًا واحدًا أو مجموعة من الأعمدة. سبب "ربط" الصور المميز هو ما يسمى التلاشي الانتقائي للترددات بسبب انتشار المسيرات المتعددة ، لكن سأتحدث عن ذلك في وقت آخر.
كيف يتم ترتيب جهاز الاستقبال؟
سأجري حجزًا على الفور حتى تتمكن من تجربة هذه الطريقة في دلو أو حتى في مسبح صغير ، ستكون قطعتان لمدة ساعة (مثل تلك المستديرة) مع موصل لبطاقة صوت ملحومة بها كافية. بالنسبة لجهاز الإرسال ، يمكنك أن تأخذ كابلًا طويلًا إلى حد ما (2-3-4-5 مترًا) وكابلًا غير محجوبًا ، مما يؤدي إلى إغلاق العنصر الكهروإجهادي باستخدام طلاء الزابون أو طبقة صغيرة من المادة المانعة للتسرب - وهو ما يكفي لعدة مرات. يتم إدخال هوائي السونار الناتج (لا ، حسناً ، ماذا؟) في مقبس سماعة الرأس.
تُظهر الصورة أدناه القطع المختلفة التي كانت في متناول اليد وقت كتابة هذا التقرير. جميع العناصر الكهروإجهادية المعروضة مناسبة تمامًا لـ "المحاولة" وعادة ما يكون هناك متجر راديو في أي
مكب للنفايات . لا يحتوي Pyatak على تأثير كهرضغطية ويوجد في الصورة للقياس.

بالنسبة لجهاز الاستقبال ، من الأفضل أخذ كبل ميكروفون محمي بنفس الموصل وبيزو ملطخ بمانع تسرب أو ورنيش في النهاية. نقوم بإدخال هذا الهوائي في مقبس الميكروفون.
للتجارب على البركة ، من الأفضل أن تأخذ نوعًا من حلقة بيزو كمرسل وتغذيها واحدة مضخمة (مكبر للصوت على TDA2030 مع محول الجرح بشكل صحيح سيستمر لعدة مئات من الأمتار في بركة جيدة
أو يمكن أن يتم جرح
5 دورات
أخرى ). بالنسبة إلى جهاز الاستقبال ، في هذه الحالة ، يلزم أيضًا مضخم أولي ويفضل مرشح نطاق ترددي. إذا كان القراء مهتمين بمعرفة المزيد عن هذا ، أخبرنا عنه في التعليقات وسنحاول كتابة مقال حول إنشاء مضخمات الطاقة ومضخمات أولية وهوائيات لاتصال السونار.
لذا ، بالعودة إلى جهاز الاستقبال ، بشكل أكثر دقة إلى جزء البرنامج الخاص به
أهم شيء في الاتصال هو التزامن وتحديد وجود إشارة مفيدة. في مثالنا ، يتم إجراء الكشف بواسطة الطاقة في النطاق: الأماكن التي يزيد فيها بشكل حاد (بداية الإطار) وحيث ينخفض بشكل حاد (نهاية الإطار) ، مع الحالة التي يجب أن يكون فيها من الإطار إلى السقوط على الأقل مدة الإطار.
على الرغم من بساطته ، فإنه يعمل بشكل جيد بشكل مدهش.
يتم جمع البيانات من بطاقة الصوت وفقًا لعينات FFTSize ، ويتم إجراء FFT عليها فورًا ويتم تخزينها على شكل "شرائح" منفصلة ، بانتظار اللحظة التي ستتم معالجتها فيها عن طريق إجراء البحث ، إليك رمزها (طريقة البحث في فئة جهاز الاستقبال):
private void Search() { int sliceIndex = 0; int frameWidth = encoder.FrameSize.Width; int minSlicesToSearch = Convert.ToInt32((frameWidth + 5) * 2); int sliceSize = encoder.FFTSize; double weight; int lastRisePosition = 0; int prevRisePosition = 0; while ((slices.Count > minSlicesToSearch) && (sliceIndex < slices.Count)) { weight = 0.0; for (int i = 0; i < sliceSize; i++) weight += Math.Abs(slices[sliceIndex][i]); double ratio = weight / previousWeight; if ((ratio >= risePeekRatio) && (sliceIndex - prevRisePosition > frameWidth)) { prevRisePosition = lastRisePosition; lastRisePosition = sliceIndex; if (lastRisePosition + (frameWidth + 5) < slices.Count) { double[][] samples = new double[frameWidth + 5][]; for (int i = 0; i < frameWidth + 5; i++) { samples[i] = new double[sliceSize]; Array.Copy(slices[lastRisePosition + i], samples[i], sliceSize); } slices.RemoveRange(0, sliceIndex); lastRisePosition = 0; if (FrameReceived != null) FrameReceived(this, new FrameReceivedEventArgs(encoder.DecodeEx(samples, 5))); lastRisePosition = sliceIndex; } } sliceIndex++; previousWeight = weight; } Interlocked.Decrement(ref isSearching); }
وهنا جزء من الكود المسؤول عن فك تشفير الصورة (Encoder.DecodeEx):
public Bitmap Decode(double[] samples, int measureCols) { int colCount = samples.Length / fftSize; if (colCount == frameSize.Width + measureCols) { int rowCount = frameSize.Height; Bitmap temp = new Bitmap(colCount, rowCount); double[] slice = new double[fftSize]; alglib.complex[] sliceC = new alglib.complex[fftSize]; int samplesCount = 0; byte component; int decodeStart = startLine; int decodeEnd = startLine + rowCount; double maxSlice; for (int x = 0; x < colCount; x++) { for (int y = 0; y < fftSize; y++) { slice[y] = samples[samplesCount]; samplesCount++; } alglib.fftr1d(slice, out sliceC); maxSlice = double.MinValue; for (int y = decodeStart; y < decodeEnd; y++) if (alglib.math.abscomplex(sliceC[y].x) > maxSlice) maxSlice = alglib.math.abscomplex(sliceC[y].x); int offset = temp.Height + decodeStart - 1; for (int y = decodeStart; y < decodeEnd; y++) { component = (byte)(255.0 * alglib.math.abscomplex(sliceC[y].x) / maxSlice); temp.SetPixel(x, offset - y, Color.FromArgb(component, component, component)); } } return temp; } else { throw new ApplicationException("Specified array length error"); } }
والآن أقترح النظر إلى نتائج التجارب على إرسال "الفيديو" ، التي أجريت في أوقات مختلفة في خزانات مختلفة.
تم تسجيل كلتا الصورتين (أدناه) في الصالون البحري الدولي في سانت بطرسبرغ في عام 2013 في جناحنا (ثم) من خلال اثنين من أجهزة الكمبيوتر المحمولة وحوض السمك.
لا يمكن تحديد ما هو مكتوب على الشارة


وإليك "مقطعي فيديو" سجلناهما في أحد خلجان بحيرة لادوغا في كاريليا ، وهما نوع من التسجيلات لهذه الطريقة (لم نجربها بعد الآن ومن غير المحتمل أن يتم ذلك) - تم الحصول على أولهما على مسافة 500 والثانية على مسافة 1000 متر :
نقل الفيديو عبر الماء ، مسافة 500 م (ملف 8.7 ميغابايت)
منذ تسجيل "الفيديو" في الوقت الحقيقي باستخدام كاميرا ويب ، سقطت أشياء غريبة مختلفة في الإطار. سيكون من المثير للاهتمام للغاية أن يخمن شخص ما ويكتب في تعليق ما في الخلفية في "الفيديو" الأخير).
لدعم حقيقة أن الطريقة تم نشرها منذ فترة طويلة -
مقالنا بالفعل لعام 2013
لقد استخدمت مكتبة
AForge الرائعة
لالتقاط صور كاميرا الويب .
يتم استخدام دالات العدد المركب و FFT من مكتبة
AlgLib الممتازة.
وكما وعدت ، فإن المشروع بأكمله في C # (VS2012) مرفق بالمقال كمواد للعمل "المنزلي". للراحة ،
المشروع والملفات الثنائية منفصلة.
يوفر العرض التوضيحي القدرة على تغيير (تحريك) نطاق التردد المشغول بالإضافة إلى تصحيح غاما لإطار الإخراج (يمكن تغيير كل شيء في الوقت الحقيقي).
ملاحظة
لم ألتقط C # منذ فترة طويلة ومن الصعب جدًا العثور على الوقت في جدول العمل ، لذا أعتذر مقدمًا عن الارتباك والتسرع في الشفرة.
PPS
أنا لا أعلق قطعة من الأسلاك ، مقابلين وقطعتين على المقال - ليس كافيًا للجميع.
Errata والملحق
- يوجد في بعض بطاقات الصوت عند الإدخال مرشح تمرير منخفض يقطع بشكل مأساوي كل شيء فوق ~ 15 كيلوهرتز (لماذا ؟؟؟).
- افتراضيًا ، يعمل المشروع التجريبي بتردد أخذ العينات يبلغ 96 كيلو هرتز ، ولكن لا تدعمه جميع بطاقات الصوت الحديثة (لماذا ؟؟؟). إذا كان الجهاز لا يستطيع 96 كيلو هرتز ، فأنت بحاجة إلى ضبط 48 كيلو هرتز في الإعدادات ، إذا لم يكن كذلك ، فمن المؤكد أن 44100 مدعوم في كل مكان ، ومع ذلك ، فإن مدة الإرسال لإطار واحد ستكون أطول في المقابل.
فيما يلي قائمة بأجهزة الكمبيوتر المحمولة وبطاقات الصوت التي يمكن اعتبارها معدات السونار الصغيرة:
- Lenovo ideapad Y510P بصوت JBL
- أسوس n55s
- أسوس K501U
- بطاقة صوت خارجية Sound Blaster X-Fi Surround 5.1 (نموذج رقم SB 1095)