Магниттик лентадан белгисиз форматтагы маалыматтарды кантип калыбына келтирдим

prehistory

Мен ретро жабдыктарды сүйүүчү болгондуктан, бир жолу Улуу Британиядагы сатуучудан ZX Spectrum+ сатып алгам. Компьютердин өзү менен кошо, мен оюндар менен бир нече аудио кассеталарды (инструкциялары менен оригиналдуу таңгагында), ошондой эле атайын белгилери жок кассетага жазылган программаларды алдым. Таң калыштуусу, 40 жылдык кассеталардагы маалыматтар жакшы окулат жана мен алардан дээрлик бардык оюндарды жана программаларды жүктөй алдым.

Магниттик лентадан белгисиз форматтагы маалыматтарды кантип калыбына келтирдим

Бирок, кээ бир кассеталарда мен ZX Spectrum компьютери тарабынан так аткарылбаган жазууларды таптым. Алар такыр башкача угулду жана айтылган компьютердеги жазуулардан айырмаланып, алар, адатта, бардык программалар менен оюндардын жазууларында бар кыска BASIC жүктөгүчтөн башташкан эмес.

Бир нече убакыт бою бул мени капа кылды - мен аларда эмне катылганын билгим келди. Эгер сиз аудио сигналды байттардын ырааттуулугу катары окуй алсаңыз, анда белгилерди же сигналдын келип чыгышын көрсөткөн нерселерди издесеңиз болот. ретро-археологиянын бир түрү.

Азыр мен бардык жолду басып, кассеталардын этикеткаларын карап, мен жылмайып жатам, анткени

жооп баары менин көз алдымда эле
Сол кассетанын этикеткасында TRS-80 компьютеринин аталышы, ал эми өндүрүүчүнүн аталышынын астында: "Radio Shack АКШда өндүрүлгөн"

(Эгер интриганы аягына чейин сактагыңыз келсе, спойлердин астына кирбеңиз)

Аудио сигналдарды салыштыруу

Биринчиден, аудио жазууларды санариптештирели. Анын кандай угулат экенин уга аласыз:


Жана адаттагыдай эле ZX Spectrum компьютеринен жазуу угулат:


Эки учурда тең жазуунун башында деп аталган нерсе бар пилоттук тон - бирдей жыштыктагы үн (биринчи жазууда ал өтө кыска <1 секунд, бирок айырмаланат). Пилоттук үн компьютерге маалыматтарды кабыл алууга даярдануу үчүн сигнал берет. Эреже катары, ар бир компьютер сигналдын формасы жана жыштыгы боюнча өзүнүн "өз" пилоттук тонун гана тааныйт.

Сигналдын формасынын өзү жөнүндө бир нерсе айтуу керек. Мисалы, ZX Spectrum анын формасы тик бурчтуу:

Магниттик лентадан белгисиз форматтагы маалыматтарды кантип калыбына келтирдим

Пилоттук тон табылганда, ZX Spectrum сигнал таанылганын көрсөтүү үчүн экрандын чегинде алмашып турган кызыл жана көк тилкелерди көрсөтөт. Пилоттук тон аяктайт синхрондук импульс, бул компьютерге маалыматтарды кабыл ала баштоо үчүн сигнал берет. Ал кыскараак узактыгы менен мүнөздөлөт (пилоттук тон жана кийинки маалыматтарга салыштырмалуу) (сүрөттү караңыз)

Синхрондоштуруу импульсун кабыл алгандан кийин, компьютер анын узактыгын өлчөө менен сигналдын ар бир көтөрүлүшүн/түшүрүүсүн жазат. Эгерде узактык белгилүү бир чектен азыраак болсо, анда 1-бит эс-тутумга жазылат, антпесе 0. Биттер байттарга чогултулат жана процесс N байт алынганга чейин кайталанат. N саны адатта жүктөлүп алынган файлдын аталышынан алынат. Жүктөө ырааттуулугу төмөнкүдөй:

  1. пилоттук тон
  2. баш (белгиленген узундук), жүктөлүп алынган маалыматтардын өлчөмүн (N), файлдын аталышын жана түрүн камтыйт
  3. пилоттук тон
  4. маалыматтардын өзү

Маалыматтар туура жүктөлгөндүгүн текшерүү үчүн, ZX Spectrum деп аталган нерсени окуйт паритеттик байт (паритеттик байт), ал жазылган маалыматтардын бардык байттарын XORing аркылуу файлды сактоодо эсептелет. Файлды окуп жатканда, компьютер алынган маалыматтардан паритеттик байтты эсептейт жана натыйжа сакталгандан айырмаланса, "R Tape жүктөө катасы" ката билдирүүсүн көрсөтөт. Тактап айтканда, компьютер окуу учурунда импульсту тааный албаса (өткөрүлбөсө же анын узактыгы белгилүү чектерге туура келбесе) бул билдирүүнү эртерээк чыгарышы мүмкүн.

Эми белгисиз сигнал кандай болорун карап көрөлү:

Магниттик лентадан белгисиз форматтагы маалыматтарды кантип калыбына келтирдим

Бул пилоттук тон. Сигналдын формасы бир кыйла айырмаланат, бирок сигнал белгилүү бир жыштыктагы кыска импульстарды кайталоодон турганы анык. 44100 Гц үлгү алуу жыштыгында "чокулардын" ортосундагы аралык болжол менен 48 үлгүнү түзөт (бул ~918 Гц жыштыгына туура келет). Келгиле, бул цифраны эстеп көрөлү.

Эми маалымат фрагментин карап көрөлү:

Магниттик лентадан белгисиз форматтагы маалыматтарды кантип калыбына келтирдим

Эгерде жеке импульстардын ортосундагы аралыкты өлчөй турган болсок, анда "узун" импульстардын ортосундагы аралык дагы эле ~48 үлгү, ал эми кыска импульстардын ортосунда - ~24 экени белгилүү болду. Бир аз алдыга карап, мен айтайын, аягында 918 Гц жыштыгы менен "маалымдама" импульстар файлдын башынан аягына чейин тынымсыз ээрчип турат. Маалыматтарды берүү учурунда эталондук импульстардын ортосунда кошумча импульс кездешсе, биз аны бит 1, болбосо 0 деп эсептейбиз деп болжолдоого болот.

Синхрондоштуруу импульсу жөнүндө эмне айтууга болот? Келгиле, маалыматтардын башын карап көрөлү:

Магниттик лентадан белгисиз форматтагы маалыматтарды кантип калыбына келтирдим

Пилоттук үн бүтөт жана маалыматтар дароо башталат. Бир аз убакыт өткөндөн кийин, бир нече ар кандай аудио жазууларды талдоодон кийин, биз маалыматтардын биринчи байт дайыма бирдей экенин таба алдык (10100101b, A5h). Компьютер маалыматтарды алгандан кийин окуй башташы мүмкүн.

Синхрондоштуруу байтындагы акыркы 1-ден кийин дароо биринчи шилтеме импульстун жылышына да көңүл бурсаңыз болот. Ал бир топ кийинчерээк маалыматтарды таануу программасын иштеп чыгуу процессинде, файлдын башындагы маалыматтар туруктуу окулбай калганда табылган.

Эми аудио файлды иштетип, маалыматтарды жүктөй турган алгоритмди сүрөттөөгө аракет кылалы.

Маалыматтар жүктөлүүдө

Биринчиден, алгоритмди жөнөкөй сактоо үчүн бир нече божомолдорду карап көрөлү:

  1. Биз WAV форматындагы файлдарды гана карап чыгабыз;
  2. Аудио файл пилоттук обон менен башталып, башында унчукпоо болбошу керек
  3. Булак файлынын үлгү алуу ылдамдыгы 44100 Гц болушу керек. Бул учурда, 48 үлгүдөгү шилтеме импульстарынын ортосундагы аралык мурунтан эле аныкталган жана биз аны программалык түрдө эсептөөнүн кереги жок;
  4. Үлгү форматы каалагандай болушу мүмкүн (8/16 бит/сүзүүчү чекит) - окуп жатканда биз аны каалаган форматка алмаштыра алабыз;
  5. Булак файлы амплитуда менен нормалдаштырылган деп ойлойбуз, ал натыйжаны турукташтырууга тийиш;

Окуу алгоритми төмөнкүдөй болот:

  1. Биз файлды эс тутумга окуйбуз, ошол эле учурда үлгү форматын 8 битке айландырабыз;
  2. Аудио маалыматтардагы биринчи импульстун ордун аныктаңыз. Бул үчүн, максималдуу амплитудасы менен үлгүнүн санын эсептөө керек. Жөнөкөйлүк үчүн биз аны бир жолу кол менен эсептейбиз. Аны prev_pos өзгөрмөсүнө сактайлы;
  3. Акыркы импульстун абалына 48 кошуңуз (pos := prev_pos + 48)
  4. Позицияны 48ге көбөйтүү биз кийинки эталондук импульстун абалына келебиз деп кепилдик бербегендиктен (лентадагы кемчиликтер, лента жетектөөчү механизмдин туруксуз иштеши ж.б.), импульс позунун абалын тууралашыбыз керек. Бул үчүн, маалыматтын кичинекей бөлүгүн (pos-8;pos+8) алып, андагы максималдуу амплитудалык маанини табыңыз. Максимумга туура келген позиция постто сакталат. Бул жерде 8 = 48/6 эксперименталдык жактан алынган константа, ал биз туура максимумду аныктай турганыбызды жана жакын жерде болушу мүмкүн болгон башка импульстарга таасир этпей турганыбызды кепилдейт. Абдан начар учурларда, импульстардын ортосундагы аралык 48ден бир топ аз же андан жогору болгондо, импульсту мажбурлап издөөнү ишке ашыра аласыз, бирок макаланын алкагында мен муну алгоритмде сүрөттөбөйм;
  5. Мурунку кадамда шилтеме импульстун такыр табылганын текшерүү керек. Башкача айтканда, эгерде сиз жөн гана максимум издесеңиз, бул импульс ушул сегментте бар экенине кепилдик бербейт. Окуу программасын акыркы жолу ишке ашырууда мен сегменттеги максималдуу жана минималдуу амплитудалык маанилердин ортосундагы айырманы текшерем жана ал белгилүү бир чектен ашып кетсе, импульстун бар экенин эсептейм. Суроо ошондой эле шилтеме импульс табылбаса эмне кылуу керек. 2 вариант бар: же маалыматтар бүтүп, унчукпай калат, же бул окуу катасы катары каралышы керек. Бирок, биз алгоритмди жөнөкөйлөтүү үчүн муну өткөрүп жиберебиз;
  6. Кийинки кадамда биз маалымат импульсунун (бит 0 же 1) бар экендигин аныкташыбыз керек, ал үчүн сегменттин ортосун (prev_pos;pos) орто_пос := (prev_pos+pos)/2ге барабар алабыз жана Сегменттеги middle_posтын кээ бир микрорайондорунда (middle_pos-8;middle_pos +8) максималдуу жана минималдуу амплитуданы эсептеп көрөлү. Эгерде алардын ортосундагы айырма 10дон көп болсо, натыйжага 1-битти жазабыз, антпесе 0. 10 - эксперименталдык жол менен алынган константа;
  7. Учурдагы абалды prev_posто сактоо (prev_pos := pos)
  8. 3-кадамдан баштап файлды толугу менен окуганга чейин кайталаңыз;
  9. Натыйжадагы бит массив байт топтому катары сакталышы керек. Окууда синхрондоштуруу байттарын эске албагандыктан, биттердин саны 8ге эселик болбошу мүмкүн жана талап кылынган бит офсет да белгисиз. Алгоритмди биринчи жолу ишке ашырууда мен синхрондоштуруу байтынын бар экенин билген эмесмин, ошондуктан ар кандай сандагы офсеттик бит менен 8 файлды сактап калдым. Алардын биринде туура маалыматтар камтылган. Акыркы алгоритмде мен A5h чейин бардык биттерди алып салам, бул мага туура чыгуу файлын дароо алууга мүмкүндүк берет

Кызыккандар үчүн Rubyдеги алгоритм
Программаны жазуу үчүн мен Ruby тилин тандадым, анткени... Мен көбүнчө аны программалайм. Опция жогорку өндүрүмдүүлүк эмес, бирок окуу ылдамдыгын мүмкүн болушунча тез кылуу милдети татыктуу эмес.

# Используем 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*")

жыйынтык

Алгоритмдин жана константалардын бир нече варианттарын сынап көрүп, мен абдан кызыктуу бир нерсеге ээ болдум:

Магниттик лентадан белгисиз форматтагы маалыматтарды кантип калыбына келтирдим

Ошентип, символдордун саптарына караганда, бизде графиктерди түзүү үчүн программа бар. Бирок, программанын текстинде ачкыч сөздөр жок. Бардык ачкыч сөздөр байт катары коддолгон (ар бир маани > 80h). Эми биз 80-жылдардагы кайсы компьютер бул форматтагы программаларды сактай аларын билишибиз керек.

Чынында, бул BASIC программасына абдан окшош. ZX Spectrum компьютери программаларды болжол менен бирдей форматта сактайт жана программаларды кассетага сактайт. Болбосо, мен ачкыч сөздөрдү каршы текшердим үстөл. Бирок, натыйжасы, албетте, терс болду.

Мен ошондой эле ошол кездеги популярдуу Atari, Commodore 64 жана башка бир нече компьютерлердин BASIC ачкыч сөздөрүн текшерип көрдүм, алар үчүн документтерди таба алдым, бирок ийгиликке жетпеди - ретро компьютерлердин түрлөрү боюнча менин билимим анчалык деле кенен эмес болуп чыкты.

Анан мен кетүүнү чечтим тизме, анан менин көз карашым өндүрүүчүнүн Radio Shack жана TRS-80 компьютерине түштү. Менин столумда жаткан кассеталар-дын этикеткаларында мына ушундай ысымдар жазылган! Мен буга чейин бул ысымдарды билчү эмесмин жана TRS-80 компьютерин жакшы билчү эмесмин, ошондуктан мага Radio Shack BASF, Sony же TDK сыяктуу аудио кассеталарды чыгаруучу, ал эми TRS-80 ойнотуу убактысы болуп көрүндү. Эмнеге жок?

Компьютер Танди/Радио Шак TRS-80

Макаланын башында мисал катары келтирген сөз болуп жаткан аудиожазуу компьютерде мындайча жасалган болушу мүмкүн:

Магниттик лентадан белгисиз форматтагы маалыматтарды кантип калыбына келтирдим

Көрсө, бул компьютер жана анын сорттору (I/Model III/Model IV ж.б.) бир убакта абдан популярдуу болгон (албетте, Россияда эмес). Белгилей кетчү нерсе, алар колдонгон процессор да Z80 болгон. Бул компьютер үчүн сиз Интернеттен таба аласыз көп маалымат. 80-жылдары компьютердик маалымат тараган журналдар. Учурда бир нече бар эмуляторлор ар кандай платформалар үчүн компьютерлер.

Мен эмуляторду жүктөп алдым trs80gp жана биринчи жолу мен бул компьютердин кантип иштегенин көрө алдым. Албетте, компьютер түстүү чыгарууну колдогон эмес, экрандын чечилиши 128x48 пикселди гана түзгөн, бирок экрандын чечкиндүүлүгүн жогорулата турган көптөгөн кеңейтүүлөр жана модификациялар болгон. Ошондой эле бул компьютердин операциялык тутумдарынын көптөгөн варианттары жана BASIC тилин ишке ашыруунун варианттары бар болчу (ал ZX Spectrumдан айырмаланып, кээ бир моделдерде ROMга “жарк эткен” да эмес жана каалаган опцияны дискеттен жүктөсө болот. OS өзү)

мен да таптым пайдалуу аудио жазууларды эмуляторлор колдогон CAS форматына айландыруу үчүн, бирок кандайдыр бир себептерден улам аларды колдонуу менен менин кассеталарымдан жазууларды окуу мүмкүн болгон жок.

CAS файлынын форматын түшүнүп, (ал синхрондоштуруу байт бар аталышты кошпогондо, менде болгон лентадагы маалыматтардын бир аз-бит көчүрмөсү болуп чыкты) Менин программасыма бир нече өзгөртүүлөр киргизилип, эмулятордо иштеген жумушчу CAS файлын чыгара алдым (TRS-80 Model III):

Магниттик лентадан белгисиз форматтагы маалыматтарды кантип калыбына келтирдим

Мен GEM пакети катары биринчи импульсту жана маалымдама импульстарынын ортосундагы аралыкты автоматтык түрдө аныктоо менен конверсиялык программанын акыркы версиясын иштеп чыктым, баштапкы коду төмөнкү сайтта жеткиликтүү: Github.

жыйынтыктоо

Биз басып өткөн жол өткөнгө болгон кызыктуу саякат болуп чыкты жана акырында жооп тапканыма кубанычтамын. Башка нерселердин арасында мен:

  • Мен ZX Spectrumда маалыматтарды сактоо форматын таптым жана аудио кассеталардагы маалыматтарды сактоо/окуу үчүн орнотулган ROM процедураларын изилдеп чыктым.
  • Мен TRS-80 компьютери жана анын сорттору менен тааныштым, операциялык системаны изилдеп чыктым, үлгү программаларды карап чыктым жана ал тургай машина коддорунда мүчүлүштүктөрдү оңдоого мүмкүнчүлүк алдым (анткени, Z80 мнемотехникасынын баары мага тааныш)
  • Аудио жазууларды CAS форматына айландыруу үчүн толук кандуу утилита жазды, ал "расмий" утилита тарабынан таанылбаган маалыматтарды окуй алат

Source: www.habr.com

Комментарий кошуу