
Я побудував macOS-додаток для виявлення фальшивого безтравного аудіо
https://ift.tt/fU1yWBo
WAV-файл не завжди відповідає заявленому.
Якщо ви завантажуєте трек з ярликом .wav з музичного магазину, ви припускаєте, що це безшумове — нестисле PCM-авіо, побіт у побіт ідентичне оригінальному мастеру. Іноді так і є. Іноді це MP3, який хтось конвертував у WAV — або випадково, або щоб показати вищу якість, ніж є насправді. Розмір файлу виглядає коректно. Бітова глибина — теж. Ваш мультимедійний плеєр читає його без проблем. Але аудіо вже зіпсовано, і жодна кількість повторного кодування не повертає те, що втратив стиснення з дискретним кодуванням.
Це називається фальшиве безтравне аудіо. Воно настільки поширене у DJ-колекціях та аудіофільських збірках, що я створив macOS-додаток — Spectro — щоб автоматично його виявляти. Цей пост про те, як працює виявлення.
Чому лоссі-скасування детектується
MP3, AAC і OGG стискають аудіо, назавжди відсікаючи частотну інформацію, яку психоакустичні моделі вважають неістотною — переважно високу частоту понад певний поріг. Зазвичай MP3 128 кбіт/с відрізає близько 16 кГц. MP3 320 кбіт/с — близько 19–20 кГц. Справжнє безпосереднє аудіо з джерела 44,1 кГц має контент до 22 кГц (границя Найквіста).
Коли хтось конвертує 128 кбіт/с MP3 у WAV, контейнер змінюється, але частотний контент не змінюється. Високі частоти, які були вилучені під час кодування MP3, зникли назавжди. Вихідний WAV-файл має характерний підпис: різке обривання у спектрі частот — плоска, темна область над порогом, де аудіо енергії просто немає.
Цей обрив — відбитокFingerпринт фальшивості.
Виявлення за допомогою FFT
Підхід виявлення — спектральний аналіз за допомогою швидкого перетворення Фур’є (FFT). FFT розкодовує аудіосигнал із часу у його складові частоти. Вивід — спектр частот, який показує, скільки енергії існує на кожній частоті у всьому треці. Аналізуючи цей спектр, ви бачите точно, де закінчується аудіоконтент.
У Swift фреймворк Apple vDSP робить FFT ефективним і простим. Ось спрощена версія ядра аналізу:
swiftimport Accelerate
func computeSpectrum(samples: [Float], fftSize: Int = 4096) -> [Float] {
let log2n = vDSP_Length(log2(Float(fftSize)))
guard let fftSetup = vDSP_create_fftsetup(log2n, FFTRadix(kFFTRadix2)) else {
return []
}
defer { vDSP_destroy_fftsetup(fftSetup) }
var real = [Float](samples.prefix(fftSize))
var imag = [Float](repeating: 0, count: fftSize )
real.withUnsafeMutableBufferPointer { realPtr in
imag.withUnsafeMutableBufferPointer { imagPtr in
var splitComplex = DSPSplitComplex(
realp: realPtr.baseAddress!,
imagp: imagPtr.baseAddress!
)
vDSP_fft_zip(fftSetup, &splitComplex, 1, log2n, FFTDirection(FFT_FORWARD))
// Compute magnitude spectrum
var magnitudes = [Float](repeating: 0, count: fftSize / 2)
vDSP_zvmags(&splitComplex, 1, &magnitudes, 1, vDSP_Length(fftSize / 2))
real = magnitudes
}
}
return real
}
Запуск цього коду на кількох кадрах аудіо (а не лише в одному вікні) та усереднення дає стабільне зображення частотного контенту всього треку. З цього середнього спектра виявлення порогу частоти — справа знайти, де висока частотна енергія зменшується нижче порогу.
Система вироку
Як тільки у вас є поріг частоти у кГц, логіка класифікації проста. Ось фактичний VerdictEngine з Spectro:
`swiftstruct VerdictEngine {
func evaluate(
cutoffKHz: Float,
fileExtension: String,
declaredKbps: Int? = nil,
sampleRate: Float? = nil
) -> Verdict {
let ext = fileExtension.lowercased()
let isLossyContainer = (ext == "mp3" || ext == "m4a")
let isLosslessContainer = (ext == "wav" || ext == "aiff" || ext == "flac")
// Низька заявлена бітрейт — сильний сигнал підробки
if let declaredKbps, declaredKbps <= 160 {
return .fake
}
// Границя Найквіста з урахуванням: FLAC на 32 кГц має Найквіста 16 кГц —
// без цієї перевірки його неправильно класифікували б як FAKE
if isLosslessContainer, let sampleRate {
let expectedNyquistKHz = (sampleRate / 2.0) / 1000.0
if abs(cutoffKHz - expectedNyquistKHz) <= 0.5 {
return .highQuality
}
}
// Класифікувати за порогом частоти
let verdictFromCutoff: Verdict
if cutoffKHz < 16 {
verdictFromCutoff = .fake
} else if cutoffKHz < 19 {
verdictFromCutoff = .medium
} else if cutoffKHz >= 20 {
verdictFromCutoff = .highQuality
} else {
verdictFromCutoff = .medium
}
// Контейнери з підвищеним стисненням (MP3, M4A) ніколи не можуть бути безслідно безсумнівно
if isLossyContainer && verdictFromCutoff == .highQuality {
return .medium
}
return verdictFromCutoff
}
}`
Три види вироку:
- LOSSLESS (highQuality) — частотний контент природно простягається до межі Найквіста. Файл відповідає тому, що заявлено.
- FAKE — виявлено різке обривання нижче 16 кГц або заявлена бітрейтність ≤ 160 кбіт/с. Файл майже напевно є транскодованим lossy-джерелом.
- MEDIUM — обрив між 16–20 кГц або контейнер з lossy-змістом високої частоти. Може бути MP3 320 кбіт/с, трек з агресивним майструванням з високим обрізанням або крек із вінілового джерела. Грані, що потребують судження.
Граничні випадки, що мають значення
Логіка класифікації проста, але правильність вимог вимагала врахування кількох нетипових випадків.
Нестандартні частоти дискретизації. FLAC, записаний на 32 кГц, має Найквіста 16 кГц — не 22 кГц. Без захисту за частотою Найквіста у вирішувачі вердиктів кожен 32-кГц безслідний файл класифікувався б як FAKE, бо поріг виглядав би як 16 кГц. Виправлення — порівняти виміряний поріг із очікуваним Найквістом для фактичної частоти дискретизації файлу, а не зупи за припущенням 22 кГц.
MP3 320 кбіт/с як WAV. MP3 320 кбіт/с, конвертований у WAV, обрізається близько до 20 кГц — майже нижче 22 кГц Найквіста. На спектрограмі це справді важко відрізнити від справного безслідного файлу на око. Вердикт класифікує такі як MEDIUM, а не LOSSLESS — це обережно, але точно: файл технічно не безслідний.
Свідоме обрізання майстерінгом. Деякі майстер-інженери навмисно застосовують обрізання високої частоти на 20 кГц. Справжній безслідний файл може мати обрив на 20 кГц і залишитися справжнім безслідним. Тому існує вирок MEDIUM — щоб уникати хибних позитивів у крайових випадках, де спектральні ознаки сумнівні.
Аудіо-оптимізатори. Інструменти на кшталт Platinum Notes обробляють аудіо та змінюють його частотний контент, через що легітимно безслідний файл може бути помилково класифікований. Це відома обмеженість і варто зафіксувати для користувачів.
Додаток
Spectro обробляє файли пакетно — перетягніть папку з 200 треками, і він за кілька хвилин надає вирок для кожного. Він працює повністю офлайн (аудіо нікуди не виходить за межі машини), що важливо для діджеїв, які працюють з нереалізованими треками або промо. Підключено до тегів Finder у macOS, тож позначені файли видно в бібліотеці одразу.
Ціна — 39 доларів США одноразової покупки для Mac, з безкоштовною пробною версією на 100 файлів, яка не потребує облікового запису.
https://getspectro.app
Проблема фальшивого безслідного аудіо зустрічається частіше, ніж думають більшість людей — будь-який діджей, який перевіряв свою бібліотеку, стикався з нею. Виявлення технічно просте, як тільки знаєш, на що дивитися. Трудність, як завжди, — крайові випадки.
Якщо у вас є запитання щодо реалізації FFT або логіки вироку, із задоволенням обговорю в коментарях.
HI-FI News
через DEV Community https://dev.to
24 квітня 2026 року об 12:04 PM
April 28, 2026 at 12:04PM

Залишити відповідь
Щоб відправити коментар вам необхідно авторизуватись.