forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   Delphi (http://forum.boolean.name/forumdisplay.php?f=66)
-   -   Как смешать wav-файлы? (http://forum.boolean.name/showthread.php?t=16382)

barsunduk 25.02.2012 05:20

Как смешать wav-файлы?
 
хочу смешать несколько файлов в один, как это делается в стандартной "звукозаписи".
I. не в курсе, как сие организовать программно?
оговорюсь сразу:
1) структура заголовка wave-файла понятна, давать ссылок на описание хеадеров не надо
2) данные будут и на входе и на выходе в стерео, помещение одного файла в левый канал, другого - в правый, не канает
3) объединяемых файлов может быть несколько, начинаться они могут не одновременно
4) суть вопроса, наверное в следующем. попалось определение собственно массива самих данных - "это значения амплитуды звукового колебания в момент времени t, с учетом частоты дискретизации (если, например, сигнал с АЦП)." что сия абракадабра значит, я как-то не понял. что мне делать с этими данными? может их тупо сложить? типа "byteMix = (byte1 or byte2 or byte3)"?
II. можно ли как-то повлиять на эти данные перед смешиванием? громкость убавить/прибавить, например?
III. если файлы в разных форматах (скажем, один 8 килогерц, другой - 41), то как их привести к общему знаменателю, как сконвертировать?
IV. не первый год возвращаюсь к этой теме. увы, так ответа и не нашел. те, кто разобрались в вопросе, жлобятся и вместо помощи традиционно советуют почитать какую-то абстрактную документацию. я бы и рад, но какую?

barsunduk 26.02.2012 01:58

Ответ: Как смешать wav-файлы?
 
почему-то интересные вещи всегда находятся уже после того, как задал вопрос на форуме. а до этого ничего не накапывается, хоть убей.
1. нашелся пример смешивания wav-файлов multiwav.zip. но дописывать еще много придется.
2. есть хороший набор компонентов для работы со звуком newac.zip, но чтобы его победить, тоже придется долго биться о стенку.
ну ладно, может, кому-то пригодятся ссылки.

Phantom 26.02.2012 08:40

Ответ: Как смешать wav-файлы?
 
Складывал wav файлы на PHP. Просто брал точки-значения амплитуды и складывал их. После сложения лимитировал до max/min значения. На слух в итоге всё выходило нормально, хотя в теории лимитирование при некоторых условиях должно резать слух, как мне кажется. Распаковывал и запаковывал сами сырые данные при помощи функций:
Код:

<?php
// ****************************************************
function readSample($handler,$bitsPerSample){
  $sample=0;
  for($b=0;$b<$bitsPerSample;$b+=8){
    $sample|=ord(fread($handler,1))<<$b;
  }
  if($sample>0x7fff) $sample-=0x10000;
  return $sample;
}
// ****************************************************
function writeSample($handler,$sample,$bitsPerSample){
  $data='';
  for($b=0;$b<$bitsPerSample;$b+=8){
    $data.=chr($sample>>$b&0xff);
  }
  return fwrite($handler,$data);
}
// ****************************************************
?>

Возможно не оптимально, делал временно костыльно для наглядности и экспериментов. Функция возвращает число - значение амплитуды у очередной точки (семпла). Чтение заголовков сделано ещё более костыльно, поэтому не привожу его тут. Потому что мне нужно работать только с файлами 44100 гц 16 бит и я заведомо знаю, что никаких левых заголовков и комментариев в контейнере нет. При наложении двух семплов делал так:
Код:

<?php
$sample = $sample1 + $sample2;
if($sample < -32768) $sample = -32768; // лимитирование до минимума при 16 бит
if($sample > 32767) $sample = 32767; // лимитирование до максимума при 16 бит
?>

Кто знает способ правильнее и оптимальнее, высказывайтесь.

barsunduk 26.02.2012 20:14

Ответ: Как смешать wav-файлы?
 
Цитата:

Сообщение от Phantom (Сообщение 220588)
$sample|=ord(fread($handler,1))<<$b;
$data.=chr($sample>>$b&0xff);

я с пхпой не знаком совсем. не расшифруешь эти строки? переведи на любой другой язык или поясни смысл словами, плз.

Цитата:

Сообщение от Phantom (Сообщение 220588)
$sample = $sample1 + $sample2;
if($sample < -32768 ) $sample = -32768; // лимитирование до минимума при 16 бит
if($sample > 32767) $sample = 32767; // лимитирование до максимума при 16 бит

спасибо за инфу. значит, накладывать один звук на другой можно весьма просто и без всяких муторных библиотек и компонентов. еще бы и сконвертировать. как-то надо любой другой формат в 16 бит / 44КГц перевести. буду думать.

Phantom 26.02.2012 23:05

Ответ: Как смешать wav-файлы?
 
Да переводить не обязательно, можно написать универсальный код с учётом любого сэмплрейта, частоты дискретизации и количества каналов. Вся эта информация есть в заголовках wav. Я же делал просто: Конвертирую mp3 в wav, редактирую wav средствами php, конвертирую wav в нужный формат (у меня это тоже mp3).

$ - с этого символа в php начинаются имена переменных
ord() - функция возвращает значение (число 0-255) ASCII символа
chr() - наоборот число конвертирует в символ

В php бинарные данные хранят в строках. Поэтому при чтении из потока 1 байта fread($handler,1) он возвращается в виде строки из одного символа. В Java, например, сразу возвращается тип byte или int, не помню точно. В php же приходится делать лишние телодвижения ord/chr.

barsunduk 26.02.2012 23:29

Ответ: Как смешать wav-файлы?
 
нашел справочник по php и во всем разобрался. я со сдвигом тупанул ">>" ..) давно не юзал.
Цитата:

Сообщение от Phantom (Сообщение 220675)
Я же делал просто: Конвертирую mp3 в wav, редактирую wav средствами php, конвертирую wav в нужный формат

чем конвертируешь? какой-то либой или тоже средствами недоступного мне php (прогу на delphi пишу), с которым не хотелось бы связываться для решения одной задачи. (как, например, не хочу учиться писать операционки и прошивать телефон, чтобы выставить дату или настроить будильник ..)

Phantom 26.02.2012 23:43

Ответ: Как смешать wav-файлы?
 
Консольная утилита ffmpeg. Работает с кучей форматов видео и аудио. Имеет поддержку отправки и получения данных через STDIN и STDOUT. Но в случае с wav у меня это не получилось, потому что как я понял при конвертировании в wav при записи всех данных, указатель возвращается назад к заголовкам (seek) и записывает размер данных (он видимо заранее не известен). А при чтении STDOUT, seek не работает. Короче поток должен быть seekable. Но это не проблема в принципе. Просто делаем системный вызов (не знаю как это делается в делфи) к ffmpeg.exe с нужными параметрами и конвертируем например mp3 в wav (wav сохраняем или в temp папке, или в какой-то папке твоего же приложения, которое ты пишешь). И после уже с wav файлом делаем что угодно.

barsunduk 27.02.2012 00:58

Ответ: Как смешать wav-файлы?
 
говорят, у ffmpeg открытый код, можно сконвертить как dll-ку и приспособить для работы без сохранения левых файлов на диск. только некоммерческая лицуха. я не рискнул в нем копаться. как оказалось, с помощью newAC все это делается проще. в общем, возвращаемся к использованию сторонних компонентов. судя по всему, без этого никуда.

ViNT 27.02.2012 02:37

Ответ: Как смешать wav-файлы?
 
Если конвертировать wav без сжатия, то можно вручную (сам не пробовал, но по логике должно быть так).
Допустим, есть wav 16 бит, его надо сконвертить в 8 бит. В 8-битном максимуму сигнала соответствует 255, в 16-биттном - 65535. Чтобы получить 8б из 16б, просто каждое значение сигнала делим на 256, для обратного преобразования наоборот умножаем на 256.
С частотой дискретизации несколько сложнее. Чтобы понизить частоту, нужно пропускать семплы (или, возможно, брать среднее, не знаю, как правильнее). То есть, чтобы получить 8 кГц из 16 кГц нужно брать каждый второй семпл, для получения 4 кГц - либо брать каждый четвертый (грубо), либо брать среднее по четырем соседним (должен быть более гладкий сигнал). Для повышения частоты дискретизации нужно делать интерполяцию (скорее всего кусочно-линейную, хотя может прокатить и кусочно-постоянная).

Как-то так. Все вышесказанное не опробовано, просто размышления на основе знаний теории обработки сигналов.

barsunduk 27.02.2012 15:12

Ответ: Как смешать wav-файлы?
 
Цитата:

Сообщение от ViNT (Сообщение 220708)
...Как-то так...

хм, теперь все встало на свои места. а то техническая документация - это такой китайский язык с бушменским акцентом для меня, русскоязычного. (из инженеров ушел, потому что стала моя пробитая башка взрываться от обилия технических терминов). а тут всё на пальцах и по-русски. большое спасибо за понятные объяснения!

DarkInside 30.03.2012 16:08

Ответ: Как смешать wav-файлы?
 
хм...в свое время делал это через консоль винды.

Код:

COPY/B Sound_1.wav + Sound_2.wav + Sound_3.wav Output.wav
Вот такая строчка объединит 3 файла в один. По моему, проще некуда:)

barsunduk 30.03.2012 16:41

Ответ: Как смешать wav-файлы?
 
Цитата:

Сообщение от DarkInside (Сообщение 224122)
хм...в свое время делал это через консоль винды.

Код:

COPY/B Sound_1.wav + Sound_2.wav + Sound_3.wav Output.wav
Вот такая строчка объединит 3 файла в один. По моему, проще некуда:)

здорово! не знал о такой возможности. жаль, что начало очередного файла нельзя указать. типа Sound_2.wav начинается на 2-й секунде от начала первого, а 3-й начинается еще через секунду ..(

SBJoker 30.03.2012 18:05

Ответ: Как смешать wav-файлы?
 
Сдаётся мне оно объеденит файлы невзирая на структуру и формат, тупо записав один файл в конец другого. Учитывая что WAV это лишь контейнер и внутри данные могут быть какими угодно, да и у каждого файла есть заголовок...

Скорее всего результат будет неожиданным.

Phantom 31.03.2012 00:56

Ответ: Как смешать wav-файлы?
 
Не пробовал, но сразу подумал так же, как и Джокер, скорее всего винда просто склеит файлы последовательно, а не так, как тебе нужно.

barsunduk 29.04.2012 02:58

Ответ: Как смешать wav-файлы?
 
Цитата:

Сообщение от Phantom (Сообщение 220588)
$sample = $sample1 + $sample2;
if( $sample < -32768 ) $sample = -32768; // лимитирование до минимума при 16 бит
if( $sample > 32767 ) $sample = 32767; // лимитирование до максимума при 16 бит
?>

поробовал. при "s1 + s2" громкое шипение. почти все результирующие значения = 32767.
при "(s1 + s2) div 2" - тише, но качество отвратное ..(
был лет 15 назад на одной сельской дискотэке в саратовской области. в "клубе" с ильичом во дворе и "росписями" на всех углах. на входе дважды сунули по пол стакана водки. молча выпил, успокоились, отстали. внутри, в потемках, однообразно размахивали ветряками полторы девушки. моргала гирляндочка светомузыки. причем в такт мелодии. удивился, что тут кто-то умеет паять. ан нет. оказалось, что проводульки были рваные и от сотрясения басами разрывался контакт. вот и весь секрет аутентичности. но самое главное ноу-хау (для чего я это все и начал рассказывать) - усилитель системы "колонка в металлическом ведре". так вот эта колонка в ведре играла гораздо лучше, чем получается звук при побайтном (вернее поinteger-ном - 16 бит же ж) смешивании. вот такая вот эпидерсия
---
перерыл все компоненты с открытым кодом. везде делают так:
res := (volume1 * sample1 + volume2 * sample2) / 2;
но ведь это тоже самое, что и
res := (sample1 + sample2) div 2;
только с фиксированной громкостью. но на выходе какое-то уг получается. (ограничители стоят)


Часовой пояс GMT +4, время: 04:11.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot