а какие есть подходы к распознаванию TZX/TAP из WAV?
Нужно было перевести wav/flac в tap, утилит по linux не нашел. Пришлось набросать свой простенький вариант, получилось вот такая процедурка на C#. На входе длительности импульсов распознанные в аудиофайле:
Для простых tap вроде неплохо работает. Но стало интересно, какие есть алгоритмы для распознавания более сложных записей с турбоблоками и т.п. для TZX?Код:static byte[][] DecodeZXTape(List<int> pulses) { const int pilot_t = 2168; // Pilot-tone pulse length const int sync1_t = 667; // Sync 1 pulse length const int sync2_t = 735; // Sync 2 pulse length const int bit0_t = 855; // Bit 0 pulse length const int bit1_t = 1710; // Bit 1 pulse length const int pilotThreshold = 256; // Minimum pilot-tone edges const int tolerancePilot = 3170-2168; const int toleranceSync = 400; const int toleranceBit = 450; var outputBlocks = new List<byte[]>(); int index = 0; while (index < pulses.Count) { // Search pilot-tone int pilotCount = 0; while (index < pulses.Count && Math.Abs(pulses[index] - pilot_t) <= tolerancePilot) { pilotCount++; index++; } if (pilotCount < pilotThreshold) { // if pilot-tone is too short skip current pulse and continue search index++; continue; } if (index + 1 >= pulses.Count || Math.Abs(pulses[index] - sync1_t) > toleranceSync || Math.Abs(pulses[index + 1] - sync2_t) > toleranceSync) { // if sync pulse is incorrect, skip current pulse and start to search new pilot-tone index++; continue; } index += 2; // skip sync pulse // Read byte stream var byteStream = new List<byte>(); byte currentByte = 0; byte currentMask = 0x80; while (index + 1 < pulses.Count) { if (pulses[index] > (bit1_t + toleranceBit) || pulses[index+1] > (bit1_t + toleranceBit)) break; var period = pulses[index] + pulses[index+1]; var isZero = Math.Abs(period - bit0_t*2) <= toleranceBit*2; var isOne = Math.Abs(period - bit1_t*2) <= toleranceBit*2; index += 2; // Check for end of bit stream if (!isOne && !isZero) break; if (isOne) currentByte |= currentMask; currentMask >>= 1; if (currentMask == 0) { byteStream.Add(currentByte); currentByte = 0; currentMask = 0x80; } } if (byteStream.Count > 0) { outputBlocks.Add(byteStream.ToArray()); byteStream.Clear(); } } return outputBlocks.ToArray(); } }




Ответить с цитированием