prehistory
ʻOiai he mea aloha i ka ʻenehana retro, ua kūʻai aku au i kahi ZX Spectrum + mai kahi mea kūʻai aku ma UK. Hoʻohui pū me ka kamepiula ponoʻī, ua loaʻa iaʻu nā cassette leo me nā pāʻani (i loko o ka pahu mua me nā kuhikuhi), a me nā papahana i hoʻopaʻa ʻia ma nā cassette me ka ʻole o nā hōʻailona kūikawā. ʻO ka mea kupanaha, hiki ke heluhelu maikaʻi ʻia ka ʻikepili mai nā cassette 40 makahiki a ua hiki iaʻu ke hoʻoiho i nā pāʻani a me nā papahana āpau mai ia mau mea.
Eia naʻe, ma kekahi mau cassette ua ʻike au i nā hoʻopaʻa leo ʻaʻole i hana ʻia e ka kamepiula ZX Spectrum. Ua kani ʻokoʻa lākou a, ʻaʻole e like me nā hoʻopaʻa ʻana mai ka kamepiula i ʻōlelo ʻia, ʻaʻole lākou i hoʻomaka me kahi bootloader BASIC pōkole, ka mea maʻamau i nā leo o nā papahana a me nā pāʻani.
No kekahi manawa ua hauʻoli kēia iaʻu - makemake nui wau e ʻike i nā mea huna i loko o lākou. Inā hiki iā ʻoe ke heluhelu i ka hōʻailona leo ma ke ʻano he kaʻina paita, hiki iā ʻoe ke ʻimi i nā huaʻōlelo a i ʻole kekahi mea e hōʻike ana i ke kumu o ka hōʻailona. He ʻano retro-archeology.
I kēia manawa ua hele au a nānā i nā lepili o nā cassette iā lākou iho, ʻakaʻaka wau no ka mea
aia ka pane i mua o koʻu mau maka a pau
Aia ma ka lepili o ka cassette hema ka inoa o ke kamepiula TRS-80, a ma lalo iho o ka inoa o ka mea hana: "Hana 'ia e Radio Shack ma USA"
(Inā makemake ʻoe e hoʻomau i ka manaʻo a hiki i ka hopena, mai hele i lalo o ka mea hao.)
Hoʻohālikelike o nā hōʻailona leo
ʻO ka mea mua, e hoʻopaʻa helu i nā leo leo. Hiki iā ʻoe ke hoʻolohe i ke kani ʻana:
A e like me ke kani mau ʻana mai ka kamepiula ZX Spectrum:
I nā hihia ʻelua, i ka hoʻomaka ʻana o ka hoʻopaʻa ʻana aia kahi mea i kapa ʻia leo pailaka - he kani o ke alapine like (ma ka hoʻopaʻa mua ʻana he pōkole loa <1 kekona, akā hiki ke ʻike ʻia). Hōʻailona ka leo pailaka i ke kamepiula e hoʻomākaukau no ka loaʻa ʻana o ka ʻikepili. Ma ke ʻano maʻamau, ʻike kēlā me kēia kamepiula i kāna leo hoʻokele "ponoʻī" ma ke ʻano o ka hōʻailona a me kona alapine.
Pono e ʻōlelo i kekahi mea e pili ana i ke ʻano hōʻailona ponoʻī. No ka laʻana, ma ka ZX Spectrum kona ʻano he ʻehā:
Ke ʻike ʻia kahi leo hoʻokele, hōʻike ka ZX Spectrum i nā pahu ʻulaʻula a me polū ma ka palena o ka pale e hōʻike ai ua ʻike ʻia ka hōʻailona. Pau ka leo pailaka puʻupuʻu syncro, e hōʻailona ana i ke kamepiula e hoʻomaka i ka loaʻa ʻana o ka ʻikepili. Hōʻike ʻia ia e ka lōʻihi pōkole (hoʻohālikelike ʻia me ka leo pilote a me nā ʻikepili ma hope) (e ʻike i ke kiʻi)
Ma hope o ka loaʻa ʻana o ka pulse sync, hoʻopaʻa ke kamepiula i kēlā me kēia piʻi a hāʻule o ka hōʻailona, e ana ana i kona lōʻihi. Inā liʻiliʻi ka lōʻihi ma mua o kahi palena, kākau ʻia ka bit 1 i ka hoʻomanaʻo, inā ʻaʻole 0. E hōʻiliʻili ʻia nā bits i loko o nā bytes a hana hou ʻia ke kaʻina hana a hiki i ka loaʻa ʻana o N bytes. Lawe ʻia ka helu N mai ke poʻo o ka faila i hoʻoiho ʻia. Penei ka hoouka ana.
- leo pailaka
- header (lōʻihi paʻa), loaʻa ka nui o ka ʻikepili i hoʻoiho ʻia (N), inoa faila a me ke ʻano
- leo pailaka
- ka ʻikepili ponoʻī
No ka hōʻoia i ka hoʻouka pono ʻana o ka ʻikepili, heluhelu ka ZX Spectrum i ka mea i kapa ʻia parity byte (parity byte), i helu ʻia i ka wā e mālama ai i kahi faila ma ka XORing i nā bytes āpau o ka ʻikepili i kākau ʻia. I ka heluhelu ʻana i kahi faila, helu ka lolouila i ka parity byte mai ka ʻikepili i loaʻa a, inā ʻokoʻa ka hopena mai ka mea i mālama ʻia, hōʻike i ka memo hewa "R Tape loading error". ʻO ka ʻōlelo koʻikoʻi, hiki i ke kamepiula ke hoʻopuka i kēia memo ma mua inā, i ka heluhelu ʻana, ʻaʻole hiki iā ia ke ʻike i kahi pulse (ʻaʻole i kūpono a i ʻole kona lōʻihi i kekahi mau palena)
No laila, e ʻike kākou i ke ʻano o kahi hōʻailona ʻike ʻole ʻia:
ʻO kēia ka leo hoʻokele. He ʻokoʻa loa ke ʻano o ka hōʻailona, akā ua maopopo ka hōʻailona o ka hana hou ʻana i nā pulu pōkole o kahi alapine. Ma ke alapine sampling o 44100 Hz, ʻo ka mamao ma waena o nā "puʻu" ma kahi o 48 mau laʻana (e like me ke alapine o ~918 Hz). E hoʻomanaʻo kākou i kēia kiʻi.
E nānā kākou i ka ʻāpana ʻikepili:
Inā mākou e ana i ka mamao ma waena o kēlā me kēia pulses, ʻike ʻia ʻo ka mamao ma waena o nā pulses "lōʻihi" mau ~ 48 mau laʻana, a ma waena o nā mea pōkole - ~ 24. Ke nānā iki nei i mua, e ʻōlelo wau i ka hopena ua ʻike ʻia nā pulses "kuʻi" me ke alapine o 918 Hz e hahai mau ana, mai ka hoʻomaka a i ka hopena o ka faila. Hiki ke manaʻo ʻia i ka wā e hoʻouna ai i ka ʻikepili, inā loaʻa kahi pulse hou ma waena o nā pulses referral, manaʻo mākou he bit 1, a i ʻole 0.
Pehea e pili ana i ka pulse sync? E nānā kākou i ka hoʻomaka o ka ʻikepili:
Hoʻopau ka leo hoʻokele a hoʻomaka koke ka ʻikepili. Ma hope iki mai, ma hope o ka nānā ʻana i kekahi mau leo leo like ʻole, ua hiki iā mākou ke ʻike he like mau ka byte mua o ka ʻikepili (10100101b, A5h). Hiki i ke kamepiula ke hoʻomaka e heluhelu i ka ʻikepili ma hope o ka loaʻa ʻana.
Hiki iā ʻoe ke hoʻolohe i ka neʻe ʻana o ka pulse kuhikuhi mua ma hope koke o ka 1 hope i ka byte sync. Ua ʻike ʻia ma hope loa ma ke kaʻina o ka hoʻomohala ʻana i kahi papahana ʻike ʻikepili, ke hiki ʻole ke heluhelu paʻa i ka ʻikepili i ka hoʻomaka ʻana o ka faila.
I kēia manawa e ho'āʻo kākou e wehewehe i kahi algorithm e hoʻoponopono i kahi faila leo a hoʻouka i ka ʻikepili.
Hoʻouka ʻikepili
ʻO ka mea mua, e nānā i kekahi mau manaʻo e mālama i ka algorithm maʻalahi:
- E noʻonoʻo wale mākou i nā faila ma ke ʻano WAV;
- Pono e hoʻomaka ka waihona leo me ka leo hoʻokele a ʻaʻole pono e hāmau ma ka hoʻomaka
- Pono ka waihona kumu i ka la'ana o 44100 Hz. I kēia hihia, ua hoʻoholo mua ʻia ka mamao ma waena o nā pulses kuhikuhi o 48 a ʻaʻole pono mākou e helu i ka programmatically;
- ʻO ka hōʻailona hōʻailona hiki ke lilo i kekahi (8/16 bits/floating point) - mai ka heluhelu ʻana hiki iā mākou ke hoʻololi iā ia i ka mea i makemake ʻia;
- Manaʻo mākou ua maʻamau ka faila kumu e ka amplitude, pono e hoʻopaʻa i ka hopena;
Penei ka heluhelu algorithm:
- Heluhelu mākou i ka faila i ka hoʻomanaʻo, i ka manawa like me ka hoʻololi ʻana i ke ʻano hoʻohālike i 8 mau bits;
- E hoʻoholo i ke kūlana o ka pulse mua i ka ʻikepili leo. No ka hana ʻana i kēia, pono ʻoe e helu i ka helu o ka hāpana me ka amplitude kiʻekiʻe. No ka maʻalahi, e helu mākou i hoʻokahi manawa me ka lima. E mālama kākou i ka prev_pos variable;
- Hoʻohui i ka 48 i ke kūlana o ka pulse hope (pos := prev_pos + 48)
- Ma muli o ka hoʻonui ʻana i ke kūlana e 48 ʻaʻole ia e hōʻoiaʻiʻo e hiki mākou i ke kūlana o ka pulse kuhikuhi e hiki mai ana (nā kīnā ʻole, ka hana paʻa ʻole o ka mīkini hoʻokele tape, a me nā mea ʻē aʻe), pono mākou e hoʻoponopono i ke kūlana o ka pulse post. No ka hana ʻana i kēia, e lawe i kahi ʻāpana liʻiliʻi o ka ʻikepili (pos-8; pos+8) a e ʻimi i ka waiwai amplitude kiʻekiʻe ma luna. E mālama ʻia ke kūlana e pili ana i ka nui ma ka pos. Maʻaneʻi 8 = 48/6 kahi hoʻokolohua i loaʻa mau, e hōʻoiaʻiʻo ana e hoʻoholo mākou i ka palena kūpono a ʻaʻole e hoʻopilikia i nā manaʻo ʻē aʻe e kokoke ana. I nā hihia maikaʻi loa, inā ʻoi aku ka liʻiliʻi o ka mamao ma waena o nā pulses ma mua o 48, hiki iā ʻoe ke hoʻokō i kahi ʻimi koi no ka pulse, akā i loko o ke ʻano o ka ʻatikala ʻaʻole wau e wehewehe i kēia ma ka algorithm;
- Ma ka hana mua, pono e nānā i ka loaʻa ʻana o ka pulse kuhikuhi. ʻO ia hoʻi, inā ʻoe e ʻimi wale i ka palena kiʻekiʻe, ʻaʻole ia e hōʻoiaʻiʻo aia ka impulse i kēia māhele. I koʻu hoʻokō hou ʻana i ka papahana heluhelu, nānā au i ka ʻokoʻa ma waena o ka nui a me ka liʻiliʻi amplitude waiwai ma kahi ʻāpana, a inā ʻoi aku ia ma mua o kahi palena, helu wau i ka hiki ʻana o kahi manaʻo. ʻO ka nīnau ka mea e hana ai inā ʻaʻole ʻike ʻia ka pulse kuhikuhi. Aia nā koho 2: ua pau ka ʻikepili a ua hāmau ʻia, a i ʻole e manaʻo ʻia he hewa heluhelu. Eia naʻe, e haʻalele mākou i kēia e hoʻomaʻamaʻa i ka algorithm;
- I ka pae aʻe, pono mākou e hoʻoholo i ka hiki ʻana o kahi pulse data (bit 0 a i ʻole 1), no kēia mākou e lawe i ka waena o ka māhele (prev_pos;pos) middle_pos e like me middle_pos := (prev_pos+pos)/2 a ma kekahi wahi o middle_pos ma ka mahele (middle_pos-8;middle_pos +8) e helu kakou i ka amplitude kiʻekiʻe a me ka palena iki. Inā ʻoi aku ka ʻokoʻa ma waena o lākou ma mua o 10, kākau mākou i ka bit 1 i loko o ka hopena, inā ʻaʻole 0. ʻO 10 ka mea mau i loaʻa i ka hoʻokolohua;
- E mālama i ke kūlana o kēia manawa ma prev_pos (prev_pos := pos)
- E hana hou mai ka ʻanuʻu 3 a hiki i ka heluhelu ʻana i ka faila holoʻokoʻa;
- Pono e mālama ʻia ke ʻano bit array ma ke ʻano he set of bytes. No ka mea ʻaʻole mākou i noʻonoʻo i ka byte sync i ka wā e heluhelu ai, ʻaʻole paha he nui o ka 8 ka helu o nā bits, a ʻaʻole ʻike ʻia ka bit offset. I ka hoʻokō mua ʻana o ka algorithm, ʻaʻole wau i ʻike e pili ana i ke ola ʻana o ka sync byte a no laila ua mālama wale i nā faila 8 me nā helu like ʻole o nā bits offset. Aia kekahi o ia mau ʻikepili pololei. Ma ka algorithm hope loa, wehe wale au i nā ʻāpana āpau a hiki i A5h, e hiki ai iaʻu ke kiʻi koke i ka faila hoʻopuka pololei
Algorithm ma Ruby, no ka poe hoihoi
Ua koho au iā Ruby i ʻōlelo no ke kākau ʻana i ka papahana, no ka mea... Hoʻolālā wau iā ia i ka hapa nui o ka manawa. ʻAʻole maikaʻi ka koho, akā ʻaʻole pono ka hana o ka wikiwiki ʻana o ka heluhelu ʻana.
# Используем 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*")
hopena
I ka ho'āʻo ʻana i nā ʻano like ʻole o ka algorithm a me nā mea mau, ua laki wau i ka loaʻa ʻana o kahi mea hoihoi loa:
No laila, i ka hoʻoholo ʻana i nā kaula kikoʻī, loaʻa iā mākou kahi papahana no ka hoʻolālā ʻana i nā kiʻi. Eia naʻe, ʻaʻohe huaʻōlelo ma ka kikokikona papahana. Hoʻopili ʻia nā huaʻōlelo a pau ma ke ʻano he bytes (kekahi waiwai> 80h). I kēia manawa pono mākou e ʻike i ka kamepiula mai ka 80s hiki ke mālama i nā polokalamu ma kēia ʻano.
ʻOiaʻiʻo, ua like loa ia me kahi papahana BASIC. Mālama ka lolouila ZX Spectrum i nā polokalamu ma kahi like like o ka hoʻomanaʻo a mālama i nā polokalamu i ka lipine. No ka hihia, ua nānā au i nā huaʻōlelo kūʻē
Ua nānā hoʻi au i nā huaʻōlelo BASIC o ka mea kaulana ʻo Atari, Commodore 64 a me nā kamepiula ʻē aʻe o ia manawa, kahi i hiki ai iaʻu ke loaʻa i nā palapala, akā ʻaʻole kūleʻa - ʻaʻole ākea koʻu ʻike i nā ʻano kamepiula retro.
A laila hoʻoholo wau e hele
Kamepiula Tandy/Radio Shack TRS-80
Malia paha ua hana ʻia ka leo leo i nīnau ʻia, aʻu i hāʻawi ai i kumu hoʻohālike ma ka hoʻomaka ʻana o ka ʻatikala, i hana ʻia ma ke kamepiula e like me kēia:
Uaʻikeʻia he mea kaulana loa kēia kamepiula a me kona mauʻano (Model I/Model III/Model IV, etc.) i ka manawa hoʻokahi (ʻoiaʻiʻo,ʻaʻole i Rusia). He mea nui ka mea i hoʻohana ʻia ʻo Z80. No kēia kamepiula hiki iā ʻoe ke loaʻa ma ka Pūnaewele
Ua hoʻoiho au i ka emulator
Ua loaa no hoi ia'u
I ka noʻonoʻo ʻana i ke ʻano o ka faila CAS (ʻo ia ka mea i hoʻololi ʻia he kope liʻiliʻi wale nō o ka ʻikepili mai ka lipine i loaʻa iaʻu ma ka lima, koe wale nō ke poʻo me ka loaʻa ʻana o kahi byte sync), ua hana wau i kahi. he mau hoʻololi i kaʻu papahana a ua hiki iā ia ke hoʻopuka i kahi faila CAS hana i hana i ka emulator (TRS-80 Model III):
Ua hoʻolālā au i ka mana hou o ka pono hoʻololi me ka hoʻoholo maʻalahi o ka pulse mua a me ka mamao ma waena o nā pulses kuhikuhi ma ke ʻano he pūʻulu GEM, loaʻa ke code kumu ma
hopena
ʻO ke ala a mākou i hele ai, ua lilo ia i huakaʻi hoihoi i ka wā i hala, a hauʻoli wau i ka hopena ua loaʻa iaʻu ka pane. Ma waena o nā mea ʻē aʻe, ʻo wau:
- Ua noʻonoʻo au i ke ʻano no ka mālama ʻana i ka ʻikepili i ka ZX Spectrum a ua aʻo i nā hana maʻamau ROM i kūkulu ʻia no ka mālama ʻana/heluhelu ʻikepili mai nā cassette leo.
- Ua kamaʻāina wau i ka kamepiula TRS-80 a me kāna mau ʻano, aʻo i ka ʻōnaehana hana, nānā i nā papahana hoʻohālike a loaʻa nō hoʻi ka manawa e hana ai i ka debugging i nā code mīkini (ma hope o nā mea āpau, ʻike ʻia nā mnemonic Z80 a pau iaʻu)
- Ua kākau i kahi pono piha no ka hoʻololi ʻana i nā leo leo i ka palapala CAS, hiki ke heluhelu i ka ʻikepili i ʻike ʻole ʻia e ka pono "official".
Source: www.habr.com