sa naunang kasaysayan
Ingon usa ka mahigugmaon sa retro hardware, nakapalit ako usa ka ZX Spectrum + gikan sa usa ka magbabaligya sa UK. Lakip sa kompyuter mismo, nakadawat ako daghang mga audio cassette nga adunay mga dula (sa orihinal nga pakete nga adunay mga panudlo), ingon man mga programa nga girekord sa mga cassette nga walaβy espesyal nga mga marka. Katingad-an, ang mga datos gikan sa 40-anyos nga mga cassette mabasa ug maayo ug ako nakahimo sa pag-download sa hapit tanan nga mga dula ug mga programa gikan kanila.
Bisan pa, sa pipila ka mga cassette nakit-an nako ang mga rekording nga klaro nga wala gihimo sa ZX Spectrum nga kompyuter. Lahi kaayo ang ilang tunog ug, dili sama sa mga pagrekord gikan sa nahisgutan nga kompyuter, wala sila magsugod sa usa ka mubo nga BASIC bootloader, nga kasagaran naa sa mga pagrekord sa tanan nga mga programa ug mga dula.
Sulod sa pipila ka mga panahon kini naghasol kanako - gusto ko nga mahibal-an kung unsa ang gitago sa kanila. Kung mabasa nimo ang signal sa audio ingon usa ka han-ay sa mga byte, mahimo nimong pangitaon ang mga karakter o bisan unsang butang nga nagpaila sa gigikanan sa signal. Usa ka matang sa retro-archaeology.
Karon nga nakaadto na ko ug tan-aw sa mga label sa mga cassette mismo, nagpahiyom ko tungod kay
ang tubag anaa sa atubangan sa akong mga mata sa tanan nga panahon
Sa label sa wala nga cassette mao ang ngalan sa TRS-80 nga kompyuter, ug ubos lang sa ngalan sa tiggama: "Gigama sa Radio Shack sa USA"
(Kung gusto nimo ipadayon ang intriga hangtod sa katapusan, ayaw pag-adto sa ilawom sa spoiler)
Pagtandi sa mga signal sa audio
Una sa tanan, atong i-digitize ang mga audio recording. Mahimo nimong paminawon kung unsa kini paminawon:
Ug sama sa naandan ang rekording gikan sa ZX Spectrum nga kompyuter motingog:
Sa duha ka mga kaso, sa sinugdanan sa recording adunay usa ka gitawag nga tono sa piloto - usa ka tunog sa parehas nga frequency (sa una nga pagrekord mubo ra kaayo <1 segundo, apan mailhan). Ang tono sa piloto nagsenyas sa kompyuter sa pag-andam sa pagdawat sa datos. Ingon sa usa ka lagda, ang matag kompyuter makaila lamang sa iyang "kaugalingon" nga tono sa piloto pinaagi sa porma sa signal ug sa frequency niini.
Kinahanglan nga isulti ang usa ka butang bahin sa porma sa signal mismo. Pananglitan, sa ZX Spectrum ang porma niini rectangular:
Kung makit-an ang usa ka tono sa piloto, ang ZX Spectrum magpakita sa nagpulipuli nga pula ug asul nga mga bar sa utlanan sa screen aron ipakita nga ang signal nahibal-an. Natapos ang tono sa piloto synchro pulse, nga nagsenyas sa kompyuter nga magsugod sa pagdawat og data. Gihulagway kini sa usa ka mas mubo nga gidugayon (itandi sa tono sa piloto ug sa sunod nga datos) (tan-awa ang numero)
Human madawat ang pulso sa pag-sync, girekord sa kompyuter ang matag pagtaas/pagkahulog sa signal, gisukod ang gidugayon niini. Kung ang gidugayon ubos pa sa usa ka piho nga limitasyon, ang bit 1 isulat sa memorya, kung dili 0. Ang mga bit gikolekta ngadto sa mga byte ug ang proseso gisubli hangtud nga ang N bytes madawat. Ang numero N kasagarang gikuha gikan sa ulohan sa na-download nga file. Ang pagkasunod-sunod sa loading mao ang mosunod:
- tono sa piloto
- header (fixed length), naglangkob sa gidak-on sa na-download nga data (N), file name ug type
- tono sa piloto
- ang datos mismo
Aron masiguro nga ang datos gikarga sa husto, ang ZX Spectrum nagbasa sa gitawag nga parity byte (parity byte), nga kalkulado kung magtipig sa usa ka file pinaagi sa XORing sa tanang byte sa sinulat nga datos. Kung nagbasa sa usa ka file, gikalkula sa kompyuter ang parity byte gikan sa nadawat nga datos ug, kung ang resulta lahi sa naluwas, gipakita ang mensahe sa sayup nga "R Tape loading error". Sa estrikto nga pagkasulti, ang kompyuter mahimong mag-isyu niini nga mensahe sa sayo pa kung, sa pagbasa, dili kini makaila sa usa ka pulso (wala o ang gidugayon niini dili katumbas sa pipila nga mga limitasyon)
Busa, tan-awon nato karon kung unsa ang hitsura sa wala mailhi nga signal:
Kini ang tono sa piloto. Ang porma sa signal lahi kaayo, apan klaro nga ang signal naglangkob sa pagsubli sa mubo nga mga pulso sa usa ka frequency. Sa sampling frequency nga 44100 Hz, ang gilay-on tali sa mga "peaks" kay gibana-bana nga 48 samples (nga katumbas sa frequency nga ~918 Hz).Atong hinumdoman kini nga numero.
Atong tan-awon karon ang data fragment:
Kung atong sukdon ang gilay-on tali sa tagsa-tagsa nga mga pulso, kini nahimo nga ang gilay-on tali sa "taas" nga mga pulso mao gihapon ang ~ 48 nga mga sample, ug tali sa mga mugbo - ~ 24. Sa pagtan-aw sa unahan gamay, isulti ko nga sa katapusan nahimo nga ang "reference" nga mga pulso nga adunay frequency nga 918 Hz nagpadayon nga nagsunod, gikan sa sinugdanan hangtod sa katapusan sa file. Mahimong hunahunaon nga kung ang pagpadala sa datos, kung ang usa ka dugang nga pulso makit-an tali sa mga reference pulse, giisip namon kini nga bit 1, kung dili 0.
Unsa ang mahitungod sa sync pulse? Atong tan-awon ang sinugdanan sa datos:
Ang tono sa piloto natapos ug ang datos magsugod dayon. Usa ka gamay nga ulahi, pagkahuman sa pag-analisar sa daghang lainlaing mga pagrekord sa audio, nahibal-an namon nga ang una nga byte sa datos kanunay nga parehas (10100101b, A5h). Ang kompyuter mahimong magsugod sa pagbasa sa datos human kini madawat.
Mahimo usab nimo nga hatagan ug pagtagad ang pagbalhin sa unang reperensiya nga pulso diha-diha dayon human sa kataposang 1st sa sync byte. Nadiskobrehan kini sa ulahi sa proseso sa pagpalambo sa usa ka programa sa pag-ila sa datos, kung ang datos sa sinugdanan sa file dili mabasa nga lig-on.
Karon atong sulayan ang paghulagway sa usa ka algorithm nga magproseso sa usa ka audio file ug mag-load sa datos.
Nagkarga sa Data
Una, atong tan-awon ang pipila ka mga pangagpas aron magpabilin nga simple ang algorithm:
- Atong tagdon lamang ang mga file sa WAV format;
- Ang audio file kinahanglan magsugod sa usa ka pilot tone ug kinahanglan dili adunay kahilom sa sinugdanan
- Ang tinubdan nga file kinahanglang adunay sampling rate nga 44100 Hz. Sa kini nga kaso, ang gilay-on tali sa mga reperensiya nga pulso sa 48 nga mga sampol determinado na ug dili na kinahanglan nga kalkulahon kini sa programmatically;
- Ang sampol nga format mahimong bisan unsa (8/16 bits/floating point) - tungod kay kung magbasa mahimo naton kini mabag-o sa gusto;
- Nagtuo kami nga ang gigikanan nga file na-normalize sa amplitude, nga kinahanglan magpalig-on sa resulta;
Ang algorithm sa pagbasa mahimong ingon sa mosunod:
- Gibasa namo ang file ngadto sa memorya, sa samang higayon nag-convert sa sample format ngadto sa 8 bits;
- Tinoa ang posisyon sa unang pulso sa audio data. Aron mahimo kini, kinahanglan nimo nga kuwentahon ang gidaghanon sa sample nga adunay labing kataas nga amplitude. Alang sa kayano, atong kuwentahon kini sa makausa sa mano-mano. Atong i-save kini sa prev_pos variable;
- Idugang ang 48 sa posisyon sa kataposang pulso (pos := prev_pos + 48)
- Tungod kay ang pagdugang sa posisyon sa 48 dili garantiya nga makaabut kami sa posisyon sa sunod nga reference pulse (mga depekto sa tape, dili lig-on nga operasyon sa mekanismo sa tape drive, ug uban pa), kinahanglan namon nga ayohon ang posisyon sa pulso pos. Aron mahimo kini, pagkuha usa ka gamay nga piraso sa datos (pos-8; pos+8) ug pangitaa ang labing taas nga kantidad sa amplitude niini. Ang posisyon nga katumbas sa kinatas-an itago sa pos. Dinhi ang 8 = 48/6 usa ka eksperimento nga nakuha nga makanunayon, nga naggarantiya nga atong mahibal-an ang husto nga maximum ug dili makaapekto sa ubang mga impulses nga mahimong duol. Sa dili maayo nga mga kaso, kung ang gilay-on tali sa mga pulso mas ubos kaysa o labaw pa sa 48, mahimo nimong ipatuman ang pinugos nga pagpangita alang sa usa ka pulso, apan sa sulud sa artikulo dili nako ihulagway kini sa algorithm;
- Sa miaging lakang, kinahanglan usab nga susihon kung nakit-an ang reference pulse. Kana mao, kung pangitaon ra nimo ang labing kadaghan, dili kini garantiya nga ang impulse naa sa kini nga bahin. Sa akong pinakabag-o nga pagpatuman sa programa sa pagbasa, akong gisusi ang kalainan tali sa maximum ug minimum amplitude values ββsa usa ka bahin, ug kon kini molapas sa usa ka limitasyon, akong giihap ang presensya sa usa ka impulse. Ang pangutana mao usab kung unsa ang buhaton kung ang reference pulse dili makit-an. Adunay 2 nga mga kapilian: bisan ang datos natapos ug ang kahilom nagsunod, o kini kinahanglan nga isipon nga usa ka sayup sa pagbasa. Bisan pa, atong laktawan kini aron mapasimple ang algorithm;
- Sa sunod nga lakang, kinahanglan naton mahibal-an ang presensya sa usa ka pulso sa datos (bit 0 o 1), tungod niini gikuha namon ang tunga-tunga sa bahin (prev_pos;pos) middle_pos nga katumbas sa middle_pos := (prev_pos+pos)/2 ug sa pipila ka kasilinganan sa middle_pos sa bahin (middle_pos-8;middle_pos +8) atong kuwentahon ang maximum ug minimum amplitude. Kung ang kalainan tali kanila labaw pa sa 10, among isulat ang gamay nga 1 sa resulta, kung dili ang 0. 10 usa ka kanunay nga nakuha sa eksperimento;
- I-save ang kasamtangan nga posisyon sa prev_pos (prev_pos := pos)
- Balika sugod sa lakang 3 hangtod atong mabasa ang tibuok file;
- Ang resulta nga bit array kinahanglang i-save isip set sa bytes. Tungod kay wala namo tagda ang sync byte sa dihang nagbasa, ang gidaghanon sa mga bits mahimong dili usa ka multiple sa 8, ug ang gikinahanglan nga bit offset wala usab mahibal-i. Sa una nga pagpatuman sa algorithm, wala ako nahibal-an bahin sa paglungtad sa sync byte ug busa gitipigan ra ang 8 nga mga file nga adunay lainlaing mga numero sa mga offset bit. Ang usa niini adunay husto nga datos. Sa katapusan nga algorithm, akong tangtangon ang tanan nga mga piraso hangtod sa A5h, nga nagtugot kanako nga makuha dayon ang husto nga file sa output
Algorithm sa Ruby, para sa mga interesado
Gipili nako si Ruby isip pinulongan sa pagsulat sa programa, tungod kay... Giprograma nako kini sa kadaghanan sa oras. Ang kapilian dili taas nga pasundayag, apan ang tahas sa paghimo sa katulin sa pagbasa sa labing kadali nga mahimo dili takus niini.
# ΠΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ 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*")
resulta
Sa pagsulay sa daghang mga variant sa algorithm ug mga makanunayon, swerte ako nga nakakuha usa ka butang nga labi ka makapaikag:
Busa, sa paghukom sa mga string sa karakter, kita adunay usa ka programa alang sa pagplano sa mga graph. Bisan pa, walaβy mga keyword sa teksto sa programa. Ang tanan nga mga keyword gi-encode ingon mga byte (matag kantidad> 80h). Karon kinahanglan naton mahibal-an kung unsang kompyuter gikan sa 80s ang makatipig sa mga programa sa kini nga format.
Sa tinuud, parehas kini sa usa ka BASIC nga programa. Ang ZX Spectrum nga kompyuter nagtipig sa mga programa sa halos parehas nga pormat sa memorya ug nagtipig sa mga programa sa pag-tape. Sa kaso lang, gisusi nako ang mga keyword batok
Gisusi usab nako ang BASIC nga mga keyword sa sikat nga Atari, Commodore 64 ug ubay-ubay nga ubang mga kompyuter niadtong panahona, diin nakit-an nako ang dokumentasyon, apan walay kalampusan - ang akong kahibalo sa mga matang sa retro nga mga kompyuter nahimo nga dili kaayo lapad.
Unya nakahukom ko nga moadto
Computer Tandy/Radio Shack TRS-80
Lagmit kaayo nga ang audio recording nga gipangutana, nga akong gihatag isip usa ka pananglitan sa sinugdanan sa artikulo, gihimo sa usa ka kompyuter nga sama niini:
Kini nahimo nga kini nga kompyuter ug ang mga lahi niini (Model I / Model III / Model IV, ug uban pa) sikat kaayo sa usa ka higayon (siyempre, dili sa Russia). Mamatikdan nga ang processor nga ilang gigamit mao usab ang Z80. Alang sa kini nga kompyuter makit-an nimo sa Internet
Gi-download nako ang emulator
Nakakita pud ko
Kay nahibal-an ang format sa CAS file (nga nahimo nga usa ka gamay nga kopya sa datos gikan sa tape nga naa na nako, gawas sa header nga adunay presensya sa usa ka sync byte), naghimo ako usa ka pipila ka mga pagbag-o sa akong programa ug nakahimo sa pag-output sa usa ka nagtrabaho nga CAS file nga nagtrabaho sa emulator (TRS-80 Model III):
Gidisenyo nako ang pinakabag-o nga bersyon sa utility sa pagkakabig nga adunay awtomatik nga pagdeterminar sa unang pulso ug ang gilay-on tali sa reference pulses isip usa ka GEM package, ang source code anaa sa
konklusyon
Ang dalan nga among giagian nahimong usa ka makaiikag nga panaw ngadto sa nangagi, ug ako nalipay nga sa katapusan akong nakaplagan ang tubag. Lakip sa ubang mga butang, ako:
- Akong nahibal-an ang format alang sa pagtipig sa datos sa ZX Spectrum ug gitun-an ang built-in nga ROM nga rutina alang sa pagtipig/pagbasa sa datos gikan sa mga audio cassette
- Nasinati nako ang TRS-80 nga kompyuter ug ang mga lahi niini, nagtuon sa operating system, nagtan-aw sa mga sample nga programa ug nakahigayon pa gani sa pag-debug sa mga code sa makina (human sa tanan, ang tanan nga Z80 mnemonics pamilyar kanako)
- Nagsulat ug bug-os nga utility para sa pag-convert sa mga audio recording ngadto sa CAS format, nga makabasa sa datos nga wala mailhi sa "opisyal" nga gamit.
Source: www.habr.com