Hvernig ég endurheimti gögn á óþekktu sniði af segulbandi

Forsaga

Þar sem ég elska aftur vélbúnað keypti ég einu sinni ZX Spectrum+ frá seljanda í Bretlandi. Fylgdi með tölvunni sjálfri fékk ég nokkrar hljóðsnældur með leikjum (í upprunalegum umbúðum með leiðbeiningum), auk forrita tekin upp á snældur án sérmerkinga. Það kom á óvart að gögn frá 40 ára gömlum snældum voru vel læsileg og ég gat hlaðið niður nánast öllum leikjum og forritum úr þeim.

Hvernig ég endurheimti gögn á óþekktu sniði af segulbandi

Hins vegar fann ég á sumum snældum upptökur sem greinilega voru ekki gerðar af ZX Spectrum tölvunni. Þeir hljómuðu allt öðruvísi og ólíkt upptökum úr nefndri tölvu byrjuðu þeir ekki með stuttum BASIC ræsiforriti, sem venjulega er til staðar í upptökum á öllum forritum og leikjum.

Í nokkurn tíma ofsótti þetta mig - ég vildi endilega komast að því hvað leyndist í þeim. Ef þú gætir lesið hljóðmerkið sem röð bæta gætirðu leitað að stöfum eða einhverju sem gefur til kynna uppruna merksins. Eins konar afturfornleifafræði.

Nú þegar ég hef farið alla leið og skoðað merkimiðana á snældunum sjálfum brosi ég því

svarið var beint fyrir framan augun á mér allan tímann
Á miðanum á vinstri snældunni er nafn TRS-80 tölvunnar og rétt fyrir neðan nafn framleiðandans: „Framleitt af Radio Shack í Bandaríkjunum“

(Ef þú vilt halda ráðabrugginu til loka, ekki fara undir spoilerinn)

Samanburður á hljóðmerkjum

Fyrst af öllu skulum við stafræna hljóðupptökurnar. Þú getur hlustað á hvernig það hljómar:


Og eins og venjulega hljómar upptakan úr ZX Spectrum tölvunni:


Í báðum tilfellum er í upphafi upptöku svokallaðs flugmannstón - hljóð á sömu tíðni (í fyrstu upptöku er það mjög stutt <1 sekúnda, en er aðgreinanlegt). Pilottónninn gefur tölvunni merki um að búa sig undir að taka á móti gögnum. Að jafnaði þekkir hver tölva aðeins sína „eigin“ flugmannstón út frá lögun merksins og tíðni þess.

Það þarf að segja eitthvað um sjálft merkjaformið. Til dæmis, á ZX Spectrum er lögun þess rétthyrnd:

Hvernig ég endurheimti gögn á óþekktu sniði af segulbandi

Þegar flugmannstónn greinist sýnir ZX Spectrum til skiptis rauðar og bláar stikur á mörkum skjásins til að gefa til kynna að merkið hafi verið þekkt. Pilottón lýkur samstilltur púls, sem gefur tölvunni merki um að byrja að taka á móti gögnum. Það einkennist af styttri tímalengd (samanborið við flugmannstóninn og síðari gögn) (sjá mynd)

Eftir að samstillingarpúlsinn hefur borist skráir tölvan hverja hækkun/fall merkis og mælir lengd þess. Ef lengdin er minni en ákveðin mörk er biti 1 skrifaður í minni, annars 0. Bitunum er safnað í bæti og ferlið er endurtekið þar til N bæti berast. Talan N er venjulega tekin úr haus niðurhalaðrar skráar. Hleðsluröðin er sem hér segir:

  1. flugmannstón
  2. haus (fast lengd), inniheldur stærð niðurhalaðra gagna (N), skráarheiti og gerð
  3. flugmannstón
  4. gögnin sjálf

Til að ganga úr skugga um að gögnin séu rétt hlaðin, les ZX Spectrum svokallaða jöfnunarbæti (parity byte), sem er reiknað út þegar skrá er vistuð með því að XORa öll bæti ritaðra gagna. Þegar skrá er lesin, reiknar tölvan jöfnunarbætið út frá mótteknum gögnum og, ef niðurstaðan er önnur en vistuð, birtir villuboðin „R Tape loading villa“. Strangt til tekið getur tölvan gefið út þessi skilaboð fyrr ef hún getur ekki greint púls við lestur (misst eða lengd hans samsvarar ekki ákveðnum mörkum)

Svo, við skulum nú sjá hvernig óþekkt merki lítur út:

Hvernig ég endurheimti gögn á óþekktu sniði af segulbandi

Þetta er flugmannstónninn. Lögun merksins er verulega frábrugðin en ljóst er að merkið felst í því að endurtaka stutta púls af ákveðinni tíðni. Við sýnatökutíðni 44100 Hz er fjarlægðin milli „tinda“ um það bil 48 sýni (sem samsvarar tíðni upp á ~918 Hz). Við skulum muna þessa mynd.

Við skulum nú líta á gagnabrotið:

Hvernig ég endurheimti gögn á óþekktu sniði af segulbandi

Ef við mælum fjarlægðina á milli einstakra púlsa kemur í ljós að fjarlægðin milli „langra“ púlsa er enn ~48 sýni, og milli stuttra - ~24. Þegar ég lít aðeins fram á veginn mun ég segja að á endanum kom í ljós að „viðmiðunar“ púlsar með tíðni 918 Hz fylgja stöðugt, frá upphafi til enda skráarinnar. Gera má ráð fyrir að við sendingu gagna, ef viðbótarpúls kemur upp á milli viðmiðunarpúlsanna, lítum við á hann sem bita 1, annars 0.

Hvað með samstillingarpúlsinn? Við skulum líta á upphaf gagna:

Hvernig ég endurheimti gögn á óþekktu sniði af segulbandi

Pilottónninn lýkur og gögnin hefjast strax. Nokkru síðar, eftir að hafa greint nokkrar mismunandi hljóðupptökur, gátum við uppgötvað að fyrsta bæti gagna er alltaf það sama (10100101b, A5h). Tölvan gæti byrjað að lesa gögn eftir að hún hefur fengið þau.

Þú getur líka tekið eftir breytingu á fyrsta viðmiðunarpúlsi strax á eftir síðasta 1. í samstillingarbæti. Það uppgötvaðist miklu seinna í því ferli að þróa gagnaþekkingarforrit, þegar ekki var hægt að lesa gögnin í upphafi skráarinnar stöðugt.

Nú skulum við reyna að lýsa reiknirit sem mun vinna úr hljóðskrá og hlaða gögnum.

Hleður gögnum

Fyrst skulum við skoða nokkrar forsendur til að halda reikniritinu einfalt:

  1. Við munum aðeins íhuga skrár á WAV sniði;
  2. Hljóðskráin verður að byrja á tilraunatóni og má ekki innihalda þögn í upphafi
  3. Upprunaskráin verður að hafa sýnishraðann 44100 Hz. Í þessu tilviki er fjarlægðin milli viðmiðunarpúlsa 48 sýna þegar ákvörðuð og við þurfum ekki að reikna það forritunarlega;
  4. Sýnissniðið getur verið hvaða snið sem er (8/16 bitar/flotpunktur) - þar sem við lestur getum við breytt því í þann sem óskað er eftir;
  5. Við gerum ráð fyrir að frumskráin sé eðlileg með amplitude, sem ætti að koma á stöðugleika í niðurstöðunni;

Lesalgrímið verður sem hér segir:

  1. Við lesum skrána inn í minni og umbreytum um leið sýnishorninu í 8 bita;
  2. Ákvarðaðu staðsetningu fyrsta púlssins í hljóðgögnunum. Til að gera þetta þarftu að reikna út fjölda sýnisins með hámarks amplitude. Til einföldunar munum við reikna það einu sinni handvirkt. Við skulum vista það í breytunni prev_pos;
  3. Bættu 48 við stöðu síðasta púls (pos := prev_pos + 48)
  4. Þar sem að auka stöðuna um 48 tryggir ekki að við komumst í stöðu næsta viðmiðunarpúls (bandagalla, óstöðug virkni segulbandsdrifbúnaðarins o.s.frv.), þurfum við að stilla stöðu púlsposans. Til að gera þetta skaltu taka lítið gagnastykki (pos-8;pos+8) og finna hámarks amplitude gildi á það. Staðsetningin sem samsvarar hámarkinu verður geymd í pos. Hér er 8 = 48/6 fasti sem fæst í tilraunaskyni, sem tryggir að við munum ákvarða rétt hámark og mun ekki hafa áhrif á aðrar hvatir sem kunna að vera nálægt. Í mjög slæmum tilfellum, þegar fjarlægðin á milli púlsa er miklu minni en eða meiri en 48, er hægt að útfæra þvingaða leit að púls, en innan umfangs greinarinnar mun ég ekki lýsa þessu í reikniritinu;
  5. Í fyrra skrefi væri einnig nauðsynlegt að athuga hvort viðmiðunarpúlsinn fyndist yfirleitt. Það er, ef þú leitar einfaldlega að hámarkinu, þá tryggir þetta ekki að hvatinn sé til staðar í þessum hluta. Í nýjustu útfærslu minni á lestrarforritinu athuga ég muninn á hámarks- og lágmarksamplitudegildum á hluta, og ef það fer yfir ákveðin mörk, tel ég tilvist hvata. Spurningin er líka hvað á að gera ef viðmiðunarpúlsinn finnst ekki. Það eru 2 valkostir: annað hvort er gögnunum lokið og þögn fylgir, eða þetta ætti að teljast lesvilla. Hins vegar munum við sleppa þessu til að einfalda reikniritið;
  6. Í næsta skrefi þurfum við að ákvarða tilvist gagnapúls (biti 0 eða 1), til þess tökum við miðjan hlutann (prev_pos;pos) middle_pos jöfn middle_pos := (prev_pos+pos)/2 og í einhverju hverfi við middle_pos á hlutanum (middle_pos-8;middle_pos +8) skulum við reikna út hámarks- og lágmarksamplitude. Ef munurinn á þeim er meiri en 10 skrifum við bita 1 inn í niðurstöðuna, annars 0. 10 er fasti sem fæst með tilraunum;
  7. Vistaðu núverandi stöðu í prev_pos (prev_pos := pos)
  8. Endurtaktu frá skrefi 3 þar til við lesum alla skrána;
  9. Bitafylki sem myndast verður að vista sem sett af bætum. Þar sem við tókum ekki tillit til samstillingarbætis við lestur gæti fjöldi bita ekki verið margfeldi af 8 og nauðsynleg bitajöfnun er einnig óþekkt. Í fyrstu útfærslu reikniritsins vissi ég ekki um tilvist sync bætisins og vistaði því einfaldlega 8 skrár með mismunandi fjölda offsetbita. Einn þeirra innihélt rétt gögn. Í síðasta reikniritinu fjarlægi ég einfaldlega alla bita allt að A5h, sem gerir mér kleift að fá strax rétta úttaksskrá

Reiknirit í Ruby, fyrir áhugasama
Ég valdi Ruby sem tungumál til að skrifa forritið, vegna þess að... Ég forrita á það oftast. Valkosturinn er ekki afkastamikill, en það verkefni að gera lestrarhraðann eins hraðan og mögulegt er er ekki þess virði.

# Используем gem 'wavefile'
require 'wavefile'

reader = WaveFile::Reader.new('input.wav')
samples = []
format = WaveFile::Format.new(:mono, :pcm_8, 44100)

# Читаем WAV файл, конвертируем в формат Mono, 8 bit 
# Массив samples будет состоять из байт со значениями 0-255
reader.each_buffer(10000) do |buffer|
  samples += buffer.convert(format).samples
end

# Позиция первого импульса (вместо 0)
prev_pos = 0
# Расстояние между импульсами
distance = 48
# Значение расстояния для окрестности поиска локального максимума
delta = (distance / 6).floor
# Биты будем сохранять в виде строки из "0" и "1"
bits = ""

loop do
  # Рассчитываем позицию следующего импульса
  pos = prev_pos + distance
  
  # Выходим из цикла если данные закончились 
  break if pos + delta >= samples.size

  # Корректируем позицию pos обнаружением максимума на отрезке [pos - delta;pos + delta]
  (pos - delta..pos + delta).each { |p| pos = p if samples[p] > samples[pos] }

  # Находим середину отрезка [prev_pos;pos]
  middle_pos = ((prev_pos + pos) / 2).floor

  # Берем окрестность в середине 
  sample = samples[middle_pos - delta..middle_pos + delta]

  # Определяем бит как "1" если разница между максимальным и минимальным значением на отрезке превышает 10
  bit = sample.max - sample.min > 10
  bits += bit ? "1" : "0"
end

# Определяем синхро-байт и заменяем все предшествующие биты на 256 бит нулей (согласно спецификации формата) 
bits.gsub! /^[01]*?10100101/, ("0" * 256) + "10100101"

# Сохраняем выходной файл, упаковывая биты в байты
File.write "output.cas", [bits].pack("B*")

Niðurstaðan

Eftir að hafa prófað nokkur afbrigði af reikniritinu og föstu, var ég heppinn að fá eitthvað mjög áhugavert:

Hvernig ég endurheimti gögn á óþekktu sniði af segulbandi

Svo, miðað við karakterstrengina, höfum við forrit til að plotta línurit. Hins vegar eru engin lykilorð í forritstextanum. Öll leitarorð eru kóðuð sem bæti (hvert gildi > 80h). Nú þurfum við að komast að því hvaða tölva frá níunda áratugnum gæti vistað forrit á þessu formi.

Reyndar er það mjög svipað BASIC forriti. ZX Spectrum tölvan geymir forrit á nokkurn veginn sama sniði í minni og vistar forrit á segulband. Bara svona ef ég athugaði leitarorðin gegn borð. Hins vegar var niðurstaðan augljóslega neikvæð.

Ég skoðaði líka BASIC lykilorðin í vinsælum Atari, Commodore 64 og nokkrum öðrum tölvum þess tíma, sem ég gat fundið skjöl fyrir, en án árangurs - þekking mín á tegundum retro tölva reyndist ekki vera svo víðtæk.

Svo ákvað ég að fara listinn, og þá féll augnaráð mitt á nafn framleiðandans Radio Shack og TRS-80 tölvunnar. Þetta eru nöfnin sem voru skrifuð á miðana á kassettunum sem lágu á borðinu mínu! Ég þekkti ekki þessi nöfn áður og þekkti ekki TRS-80 tölvuna þannig að mér sýndist Radio Shack vera hljóðkassettuframleiðandi eins og BASF, Sony eða TDK og TRS-80 væri spilunartíminn. Af hverju ekki?

Tölva Tandy/Radio Shack TRS-80

Það er mjög líklegt að umrædd hljóðupptaka, sem ég nefndi sem dæmi í upphafi greinarinnar, hafi verið gerð í tölvu eins og þessari:

Hvernig ég endurheimti gögn á óþekktu sniði af segulbandi

Það kom í ljós að þessi tölva og afbrigði hennar (Model I/Model III/Model IV o.s.frv.) voru mjög vinsælar á sínum tíma (auðvitað ekki í Rússlandi). Það er athyglisvert að örgjörvinn sem þeir notuðu var líka Z80. Fyrir þessa tölvu er hægt að finna á netinu mikið af upplýsingum. Á níunda áratugnum var tölvuupplýsingum dreift í tímaritum. Í augnablikinu eru nokkrir hermir tölvur fyrir mismunandi vettvang.

Ég sótti keppinautinn trs80gp og í fyrsta skipti gat ég séð hvernig þessi tölva virkaði. Að sjálfsögðu studdi tölvan ekki litaúttak, skjáupplausnin var aðeins 128x48 dílar, en það voru margar viðbætur og breytingar sem gætu aukið skjáupplausnina. Það voru líka margir möguleikar fyrir stýrikerfi fyrir þessa tölvu og möguleikar til að innleiða BASIC tungumálið (sem, ólíkt ZX Spectrum, í sumum gerðum var ekki einu sinni „flassað“ inn á ROM og hægt var að hlaða hvaða valmöguleika sem er af disklingi, rétt eins og stýrikerfið sjálft)

Ég fann líka gagnsemi að breyta hljóðupptökum í CAS snið, sem er stutt af hermi, en einhverra hluta vegna var ekki hægt að lesa upptökur af snældum mínum með þeim.

Eftir að hafa fundið út CAS skráarsniðið (sem reyndist vera bara smátt fyrir smá afrit af gögnunum af spólunni sem ég hafði þegar við höndina, nema hausinn með samstillingarbæti), gerði ég nokkrar breytingar á forritinu mínu og gat gefið út virka CAS skrá sem virkaði í keppinautnum (TRS-80 Model III):

Hvernig ég endurheimti gögn á óþekktu sniði af segulbandi

Ég hannaði nýjustu útgáfuna af umbreytingarforritinu með sjálfvirkri ákvörðun á fyrsta púls og fjarlægð milli viðmiðunarpúlsa sem GEM pakka, frumkóði er fáanlegur á GitHub.

Ályktun

Leiðin sem við höfum farið reyndist heillandi ferð inn í fortíðina og ég fagna því að á endanum fann ég svarið. Meðal annars, ég:

  • Ég fann út sniðið til að vista gögn í ZX Spectrum og rannsakaði innbyggðu ROM venjurnar til að vista/lesa gögn úr hljóðsnældum
  • Ég kynntist TRS-80 tölvunni og afbrigðum hennar, kynnti mér stýrikerfið, skoðaði sýnishorn af forritum og fékk jafnvel tækifæri til að kemba í vélkóðum (enda eru öll Z80 minnismerkin mér kunnugleg)
  • Skrifaði fullbúið tól til að breyta hljóðupptökum í CAS snið, sem getur lesið gögn sem eru ekki viðurkennd af „opinbera“ tólinu

Heimild: www.habr.com

Bæta við athugasemd