در حال بارگذاری 0%
// منو.exe
خانه رزومه بلاگ تماس سفارش
English فارسی
~/blog / technology / dial-up-screech

آن صدای جیغِ دایل‌آپ هنگام وصل شدن به اینترنت چه بود؟

شماره‌ی شرکت اینترنت را که می‌گرفتی، اول همه‌چیز عادی بود: بوق آزاد، چند کلیکِ شماره‌گیری، زنگ. اما به‌محض اینکه آن‌طرف جواب می‌داد، تلفن خانه دیوانه می‌شد؛ چند ثانیه جیغ و قارقارِ شبیه هیچ زبان انسانی. بعد ناگهان سکوت — و همان علامت آشنا که اینترنت وصل بود.

بیشتر ما گوشه‌ی چشم به مودم نگاه می‌کردیم و فکر می‌کردیم «دارد کارش را می‌کند». اما آن صدا صدای کار کردن نبود؛ خودِ مکالمه بود. کلمه‌به‌کلمه هم معنی داشت. و عجیب‌تر اینکه برای شنیدنش اصلاً به مودم نیاز نداشتید — همان گوشی معمولیِ روی میز، کافی بود.

آن صدای جیغِ دایل‌آپ هنگام وصل شدن به اینترنت چه بود؟

# جواب کوتاه: آن صدا مکالمه‌ی دو کامپیوتر بود

آن‌طرف خط هم یک مودم بود — مال شرکت اینترنت. قبل از اینکه حتی یک بایت داده رد و بدل شود، این دو ماشین باید با هم آشنا می‌شدند: زبان مشترک انتخاب می‌کردند، خط تلفن را می‌آزمودند و روی بیشترین سرعتِ ممکنِ آن شب توافق می‌کردند. به کل این مراسم می‌گویند handshake — دست‌دادن. آن جیغ، دست‌دادنِ دو ماشین بود؛ بلندترین و پرحرف‌ترین دست‌دادن تاریخ.
اما چرا با گوشی معمولی هم شنیده می‌شد؟ چون این مکالمه در همان باندی سفر می‌کرد که صدای خودِ شما در خط تلفن سفر می‌کند. مودمِ آن‌طرف، موج صوتی‌نما را داخل سیم می‌فرستاد و سیم هم که نمی‌فهمید تولیدکننده‌اش انسان است یا ماشین؛ فقط موج را می‌رساند. گوشی معمولی عملاً یک بلندگو بود که وسط مکالمه‌ی دو ماشین گیر کرده بود. برای همین بچه‌های آن سال‌ها می‌توانستند شماره‌ی شرکت اینترنت را بگیرند و فقط با گوشی، بدون هیچ مودمی، «فضایی‌ها» را بشنوند — و بترسند.
حالا بیایید همان مکالمه را صحنه‌به‌صحنه گوش کنیم. چون از اولین بوق تا آخرین «ششش»، همه‌چیز معنی داشت:
1
بوق آزاد و شماره‌گیری — خط خالی است؛ هر کلید دو بوق خالص می‌فرستد
2
زنگ و بوق جواب — مودمِ آن‌طرف با بوق ۲۱۰۰ هرتز خودش را معرفی می‌کند
3
آزمون خط و توافق سرعت — همان بخش جیغ؛ نویز و اکو اندازه‌گیری می‌شود
4
اتصال برقرار — صدای پیوسته‌ی «ششش» یعنی داده در حال عبور

# چرا اصلاً اینترنت سوار بر صدای تلفن بود؟

شبکه‌ی تلفن برای یک کار ساخته شده بود: بردن صدای انسان از خانه‌ای به خانه‌ای. برای همین تمام مسیر — فیلترها، تقویت‌کننده‌ها، سیم‌چینی — طوری تنظیم شده بود که فقط موج‌هایی در محدوده‌ی حدود ۳۰۰ تا ۳۴۰۰ هرتز سالم عبور کنند؛ همان باندی که گفتار انسان در آن زندگی می‌کند. چیزی زیر آن باند و بالای آن باند، به‌سادگی دور ریخته می‌شد.
برای شبکه هم هیچ فرقی نمی‌کرد این موج حاصل ارتعاش تارهای صوتی یک انسان باشد یا حساب‌شده‌ترین موج الکترونیکی دنیا؛ فقط باید در همان باند می‌ماند. پس مودم کار هوشمندانه‌ای کرد: داده را به شکل صدا درآورد. بیت‌هایی که باید می‌رسیدند، به فرکانس و فاز و دامنه‌ی موج‌هایی تبدیل شدند که از نظر تلفن «صدا» بودند. تلفن فکر می‌کرد دارد صدا جابه‌جا می‌کند؛ در واقع دارد کد جابه‌جا می‌کند.
همین نکته جواب سؤال اصلی را هم می‌دهد: چرا آن‌قدر جیغ؟ چون داده‌ی فشرده در تمام باند صوتی پهن می‌شود — نه سکوت دارد، نه مکث، نه ریتم. صدای انسان موج‌های منظم و پیش‌بینی‌پذیر است؛ جریان بیت‌ها موج‌های تقریباً تصادفی در همه‌ی فرکانس‌ها. چیزی که تقریباً تصادفی باشد، به گوش انسان شبیه جیغ است. آن صدا «بد» صدا نمی‌داد؛ دقیقاً همان‌طوری بود که داده‌ی خالص باید صدا بدهد.
صدای انسان

موج‌های منظم و ریتم‌دار، با سکوت و مکث — برای گوشِ انسان بهینه شده است

صدای داده

تقریباً تصادفی، پخش در تمام باند ۳۰۰ تا ۳۴۰۰ هرتز، بدون حتی یک لحظه سکوت — برای مودمِ گیرنده بهینه است، نه برای گوش

# قبل از جیغ، بوق‌ها: هر کلید دو بوق داشت

مکالمه از همان اولین بوق شروع شده بود و ما فقط نمی‌دانستیم. بوق آزاد یعنی «خط خالی است» — دو موج خالص ساده روی هم. و وقتی شماره می‌گرفتید، هر کلید دو بوق می‌فرستاد: یکی از گروه فرکانس‌های ردیف، یکی از گروه ستون. به این سیاست می‌گویند DTMF — دو تُنِ چندفرکانسی:
۱۲۰۹ هرتز ۱۳۳۶ هرتز ۱۴۷۷ هرتز
۶۹۷ هرتز ۱ ۲ ۳
۷۷۰ هرتز ۴ ۵ ۶
۸۵۲ هرتز ۷ ۸ ۹
۹۴۱ هرتز * ۰ #
key 5 = 770 Hz + 1336 Hz
هر کلید = ترکیب یک فرکانس ردیف و یک فرکانس ستون؛ شبکه از روی همین جفت، رقم را می‌فهمد
چرا دو بوق، نه یکی؟ برای مقاومت در برابر دروغ. اگر هر رقم فقط یک بوق داشت، هر نویز تک‌فرکانسیِ سر راه می‌توانست یک رقم جعل کند. اما جفت‌فرکانس‌ها را باید دقیقاً با هم آمد؛ اتفاق نادری است. (و همین ساختارِ «هر کلید یک آکورد» باعث می‌شد بشود با کلیدهای تلفن ملودی نواخت — کسی که ستاره و مربع را به‌جا بوق می‌زد، عملاً برنامه‌نویسِ یک ساز بود.)
بعد از آخرین رقم، زنگ برگشتی می‌آمد. و این‌بار موجودی که گوشی را برمی‌دارد انسان نیست. یک ماشین است که صدای زنگ را نه با گوش، با مدار می‌شنود.

# بوق ۲۱۰۰ هرتز: «سلام، من انسان نیستم»

مودمِ شرکت اینترنت در جواب، به‌جای «بله؟» یک بوق پیوسته‌ی ۲۱۰۰ هرتزی می‌فرستاد؛ اسمش بوق جواب است. این بوق دو کار هم‌زمان می‌کرد. کار اول اعلام هویت بود: «این‌طرفِ خط یک ماشین است». کار دوم فنی‌تر: مودم شما با همین بوق شروع به شناختن خط می‌کرد — می‌سنجید که صدایش با چه تأخیر و چه تضعیفی برمی‌گردد، تا بعداً بتواند پژواک خودش را از صدای طرف مقابل جدا کند.
بعد ردیفی از بوق‌های کوتاهِ دوتایی می‌آمد — منوی قابلیت‌ها. هر مودم با همین بوق‌ها لیست زبان‌هایی که بلد است را می‌خواند؛ مثل دو نفر که قبل از شروع مذاکره کارت ویزیت رد و بدل می‌کنند: «من این‌ها را می‌توانم، تو چه؟». دو طرف بزرگ‌ترین زبان مشترک را برمی‌دارند و می‌روند سراغ مرحله‌ی اصلی. همان مرحله‌ای که اسم مقاله را رویش گذاشتیم.

# جیغ اصلی: آزمون خط و چانه‌زنی بر سر سرعت

حالا دو مودم شروع می‌کنند به فرستادن الگوهایی که هر دو از قبل رویشان توافق کرده‌اند — همین قسمتِ «قارقار» است. منطقش به‌اندازه‌ی یک ترفند آزمایشگاهی تمیز است: مودم گیرنده دقیقاً می‌داند چه موجی باید به آن برسد. هر تفاوتی میان «فرستاده‌شده» و «رسیده» اثر خودِ خط است: نویز کدام فرکانس‌ها را می‌بلعد، کدام‌ها بیشتر تضعیف می‌شوند، صدا با چند میلی‌ثانیه تأخیر برمی‌گردد. با همین چند ثانیه، مودم تنظیماتش را برای همان خط، همان شب، همان‌لحظه کوک می‌کند.
نتیجه‌ی آزمون مستقیماً به سرعت تبدیل می‌شود. خط تمیز بود؟ توافق روی ۵۶ کیلوبیت بر ثانیه — سقف استاندارد V.90. خط شلوغ بود؟ سرعت می‌آمد پایین، چون سرعتِ بیشتر یعنی بیت‌ها به هم نزدیک‌تر و هضم‌شان برای خط نویزی سخت‌تر. پس آن جیغِ چندثانیه‌ای در واقع این جمله بود: «بگذار ببینم همین امشب چقدر می‌توانی تند حرف بزنی».
خط تمیز

نویز کم → بیت‌ها فشرده‌تر جا می‌شوند → توافق روی سقف سرعت: ۵۶ کیلوبیت بر ثانیه (V.90)

خط نویزی

نویز زیاد → بیت‌های فشرده به هم می‌ریزند → سرعت پایین می‌آید تا انتقال قابل‌اعتماد بماند

و بعد از توافق؟ صدای «ششش» پیوسته و همیشگی: خودِ داده در حال عبور. دیگر بوق تمیز و الگوی مشخصی نبود؛ صدها بیت در هر لحظه، در تمام باند، پشت سر هم. و هر چیزی که این جریان را به هم می‌ریخت — مثلاً برداشتن گوشی در اتاق دیگر — اتصال را می‌بُرید. کلاسیک‌ترین دعوای خانوادگیِ آن سال‌ها از همین‌جا می‌آمد: «گوشی را نگذار!» یعنی «الگوی توافق‌شده‌ی مودم را خراب نکن!».

# بیایید با Python آن صدا را از نو بسازیم

برای اینکه با گوش خودمان بفهمیم «معنی‌دار» یعنی چه، کل مکالمه را فاز‌به‌فاز بازسازی می‌کنیم و در یک فایل WAV ذخیره می‌کنیم: بوق آزاد، شماره‌گیری، زنگ برگشتی، بوق جواب، منوی قابلیت‌ها، آزمون خط و صدای اتصال. فقط یک نکته‌ی لذت‌بخش قبل از کد: نرخ نمونه‌برداری را می‌گذاریم 8000 — دقیقاً همان نرخی که قلب شبکه‌ی تلفن با آن کار می‌کرد، چون هیچ‌وقت چیزی بالاتر از ۴ کیلوهرتز برای حمل نداشت. فایل ما از همان قیدی استفاده می‌کند که شبکه‌ی تلفن به مودم‌ها تحمیل می‌کرد:
dialup_synth.py
# dialup_synth.py - rebuild the screech, phase by phase
import wave, math, random, struct
 
SR = 8000 # the phone network's own sampling rate
 
DTMF = {'1':(697,1209), '2':(697,1336), '3':(697,1477),
        '4':(770,1209),  '5':(770,1336),  '6':(770,1477),
        '7':(852,1209),  '8':(852,1336),  '9':(852,1477),
        '*':(941,1209),  '0':(941,1336),  '#':(941,1477)}
 
def tone(freqs, sec, amp=0.30):
    out = []
    for i in range(int(SR*sec)):
        t = i / SR
        s = sum(math.sin(2*math.pi*f*t) for f in freqs)
        out.append(amp * s / len(freqs))
    return out
 
def silence(sec):
    return [0.0] * int(SR*sec)
 
def band_noise(sec, amp=0.30, lo=300, hi=3400):
    # random data spread over the voice band - that's why it screams
    out, y_hi, y_lo = [], 0.0, 0.0
    k_hi = math.exp(-2*math.pi*hi/SR)
    k_lo = math.exp(-2*math.pi*lo/SR)
    for _ in range(int(SR*sec)):
        x = random.uniform(-1, 1)
        y_hi = x + k_hi*(y_hi - x)
        y_lo = y_hi + k_lo*(y_lo - y_hi)
        out.append(amp * (y_hi - y_lo))
    return out
 
audio  = silence(0.3)
audio += tone((350, 440), 0.6)           # dial tone: an empty line
audio += silence(0.2)
for d in "808080":                   # dialing the ISP number
    audio += tone(DTMF[d], 0.08, 0.35)
    audio += silence(0.06)
audio += tone((440, 480), 0.9, 0.25)   # ringback tone
audio += silence(0.4)
audio += tone((2100,), 1.4)            # ANSWER tone: "a modem here"
audio += silence(0.2)
for f in [(1000,1600), (1100,1700), (1000,1700), (1100,1600)]:
    audio += tone(f, 0.06)            # V.8 menu bongs (simplified)
    audio += silence(0.02)
audio += silence(0.2)
audio += band_noise(1.6, 0.40)          # TRAINING: probing the line
audio += band_noise(3.0, 0.18)          # connected: the hiss IS the data
 
frames = b''.join(struct.pack('<h', int(max(-1, min(1, s)) * 32767))
                   for s in audio)
with wave.open('dialup.wav', 'w') as w:
    w.setnchannels(1); w.setsampwidth(2); w.setframerate(SR)
    w.writeframes(frames)
print(f"dialup.wav written - {len(audio)/SR:.1f} seconds of nostalgia")
این بازسازیِ آزاد است: ترتیب فازها و فرکانس‌های کلیدی واقعی است، اما جزئیات دقیق پروتکل‌ها ساده شده تا کد در چند ثانیه اجرا شود و فایل ده‌ثانیه‌ای بدهد. اجرایش کنید و پخشش کنید — همان پروازِ ده‌ثانیه‌ای به گذشته:
output.txt
dialup.wav written - 10.0 seconds of nostalgia
حالا فایل را با دقت گوش کنید. هر تکه‌اش یک جمله است: بوق یکنواخت اول «خط خلوت است»؛ دوتایی‌های کوتاه «هشت، صفر، هشت...»؛ بوق ممتد «من ماشینم»؛ نویز وحشی وسط «بگذار خط را بسنجیم»؛ و شششِ آخر «داریم کد رد و بدل می‌کنیم». همان جیغی که سال‌ها بی‌معنی شنیده بودیم، الان صحنه‌به‌صحنه زیرنویس دارد.

# برعکسش کنیم: از صدا، شماره را بیرون بکشیم

اگر ادعای ما درست باشد — اینکه آن صدا داده بود، نه نویز — باید بشود از روی صدا، داده را پس گرفت. در همان فایل WAV، شماره‌ای که در کد گرفتیم را الان از روی خود صدا پیدا می‌کنیم. ابزارش الگوریتم Goertzel است: مثل یک رادار کوچک که برای هر فرکانسِ مشکوک می‌پرسد «تو داخل این تکه صدا چقدر هستی؟»:
dialup_decode.py
# dialup_decode.py - the sound was data: read the number back
import wave, math, struct
 
SR, N = 8000, 400                  # 50 ms analysis windows
ROWS, COLS = (697,770,852,941), (1209,1336,1477)
KEY = {(697,1209):'1', (697,1336):'2', (697,1477):'3',
       (770,1209):'4', (770,1336):'5', (770,1477):'6',
       (852,1209):'7', (852,1336):'8', (852,1477):'9',
       (941,1209):'*', (941,1336):'0', (941,1477):'#'}
 
def goertzel(win, f):
    k = 2 * math.cos(2*math.pi*f/SR)
    s1 = s2 = 0.0
    for v in win:
        s0 = v + k*s1 - s2
        s2, s1 = s1, s0
    return s1*s1 + s2*s2 - k*s1*s2
 
with wave.open('dialup.wav') as w:
    raw = w.readframes(w.getnframes())
x = [v/32768 for v in struct.unpack('<%dh' % (len(raw)//2), raw)]
 
digits, run, current = [], 0, None
for i in range(0, len(x)-N, 80):   # slide by 10 ms
    win = x[i:i+N]
    e = sum(v*v for v in win)      # total energy of this window
    p = {f: goertzel(win, f) for f in ROWS+COLS}
    r = max(ROWS, key=lambda f: p[f])
    c = max(COLS, key=lambda f: p[f])
    # two pure tones dominating the spectrum = a key is held
    key = (r, c) if p[r]+p[c] > 0.1*N*e else None
    if key == current: run += 1
    else: current, run = key, 1
    if key and run == 2:           # stable across windows = real press
        digits.append(KEY[key])
 
print("dialed:", ' '.join(digits))
output.txt
dialed: 8 0 8 0 8 0
همین. از میان ده ثانیه صدا، برنامه فقط با گوش دادن، شماره‌ای را درآورد که در کد گرفته بودیم. مودمِ شرکت اینترنت هم دقیقاً همین کار را می‌کرد — فقط با فیلترهای دقیق‌تر، در چند میلی‌ثانیه، و برای همه‌ی ارقام همه‌ی مشترکین. آن جیغ از اول داده بود؛ ما فقط زبانش را بلد نبودیم.
ⓘ
چرا Goertzel و نه FFT؟ FFT کل طیف را یک‌جا می‌دهد؛ اما وقتی — مثل گیرنده‌ی DTMF — فقط هفت فرکانس مشخص مهم است، Goertzel همان چند فرکانس را جداگانه و ارزان‌تر محاسبه می‌کند. برای همین چیپ‌های تلفن واقعی هم تشخیص DTMF را با همین الگوریتم انجام می‌دادند.

# آزمایشگاه: شماره بگیر و فازها را زیرنویس‌دار بشنو

حالا نوبت شماست. دکمه را بزنید تا همین مکالمه، زنده و همین‌جا در مرورگر ساخته و پخش شود — و این‌بار هر ثانیه زیرنویس دارد که «الان چه خبر است». بعد از برقراری اتصال، دکمه‌ی «برداشتن گوشی» هم فعال می‌شود؛ بزنیدش تا ببینید چرا آن دعوای خانوادگی، فیزیک داشت:
dialup_lab.exe — interactive
صدا همین‌جا با Web Audio ساخته می‌شود — همان فازهای مقاله، همان فرکانس‌ها.
گوشی بردار و دکمه را بزن…
ⓘ
چرا برداشتن گوشی اتصال را می‌بُرید؟ گوشی تلفن یک مدار موازی روی خط می‌سازد: امپدانس می‌افتد، سطح سیگنال و نویز عوض می‌شود و الگویی که دو مودم با آن توافق کرده بودند دیگر منطبق بر آنچه می‌رسد نیست. مودم نمی‌داند «گوشی برداشته شده»؛ فقط می‌بیند داده‌ها دیگر معنی ندارند — و مثل هر ارتباطی که اعتمادش خراب شود، می‌بُرد.

# و بعد، دیگر هیچ‌کس جیغ نکشید

دایل‌آپ وقتی رفت که داده لازم نداشت خودش را عکسِ صدا جا بزند: ADSL همان سیم تلفن را نگه داشت، اما داده را از فرکانس‌های بالای باند صوتی رد کرد — جایی که تلفن اصلاً گوش نمی‌داد. نتیجه: خط همیشه وصل بود و تلفن خانه همیشه آزاد.
اما آن مراسم تمام نشد؛ فقط بی‌صدا شد. مودم‌ها هنوز هم — وای‌فای، 4G، 5G، روتر خانه‌تان — قبل از هر انتقال جدی، همدیگر را می‌آزمایند و روی سرعت و زبان مشترک توافق می‌کنند. فرق فقط این است که مذاکره به فرکانس‌ها و کانال‌هایی رفت که نه گوش ما می‌شنود، نه گوشیِ دیواربه‌دیوار. آن شب‌ها صدا را می‌شنیدیم و معنی را نمی‌فهمیدیم؛ حالا معنی هر روز دور و بر ماست و صدا را که نداریم.
takeaway.txt
تلفن برای حرف‌زدنِ آدم‌ها ساخته شده بود؛
مودم‌ها یاد گرفتند جیغ بزنند.

# مقالات مرتبط