| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Звук, графика и видео > Получение данных из WAV |
| Автор: Black_Joker 13.4.2006, 19:32 | ||
| Здравствуйте. Мне надо получить данные из wav. Делаю следующее... В итоге получаю несколько нулевых значений. Подскажите где ошиПка.
|
| Автор: Alexeis 14.4.2006, 09:15 | ||
Black_Joker, вы невнимательно читали мою статью, там было описано, что байты в словах в файле записываются в обратном порядке, вначале младшие затем старшие, т.о. указанный код
читает совсем не то что надо. У меня описан рабочий пример чтения Wav файлов. Не обижайтесь на критику но код написан кошмарно нерационально, а поэтому сложно! Предположение о том что ChunkSize = 18 совсем неверно (часто это значение равно 16) Если вам не нравятся потоки, то воспользуйтесь нетипизированными файлами, это куда проще и понятней |
| Автор: Black_Joker 14.4.2006, 12:29 |
| Применил пример из статьи. Порадовался, что так много сторочек в Мемо1. А как получить данные, так и не понял. Как работать с TMemoryStream??? К примеру, мне нужно вывести данные в текстовый файл. Один столбик - левый канал, другой столбик - правый (если есть). Как это сделать? |
| Автор: Alexeis 14.4.2006, 14:07 | ||
| Так это было для того чтобы еще раз посмотреть внутреннюю структуру Wav - в реальной программе их надо удалять (в смысле код вывода этих строчек) Из memoryStream данные получить легко
|
| Автор: Black_Joker 25.4.2006, 17:43 | ||
| Не пойму как вывести данные в поле Мемо? делаю следующее... получаю только данные строк Memo1.Lines.Add('SampleCount: ' + IntToStr(SampleCount)); ... Memo1.Lines.Add('Bits: ' + IntToStr(BitsPerSample)); звук однокональный, 16 бит. Как переделать для 8 бит?
|
| Автор: Alexeis 26.4.2006, 09:11 | ||
|
| Автор: Black_Joker 26.4.2006, 09:28 |
| Понятно. Спасибо. А что у меня в проге не правильно? Почему не выводит данные? |
| Автор: Alexeis 26.4.2006, 09:53 |
| Black_Joker, я ошибся не b := word(s) div 2; а b := word(s) shr 8; |
| Автор: Alexeis 26.4.2006, 10:24 | ||
Зачем нужен сдвиг на 4 байта после чтения, Кроме того если размер чанка fact больше 8 байт то остальные данные запишутся в пространство занятое любыми другими данными т.е. неизбежно приведет к ошибке! |
| Автор: Black_Joker 26.4.2006, 21:09 |
| признаю свою безмерную тупость и т.д. ... Нельзя ли довести до ума мою прогу и выложить вновь. |
| Автор: Alexeis 27.4.2006, 10:42 |
| Black_Joker, чтоб исправить программу надо знать источник файлов, какой програмой создаются и какие чанки содержаться, потому что данная програма привязана к какому-то типу wav. Пример универсальной программы для чтения я приводил... |
| Автор: Black_Joker 27.4.2006, 13:33 |
| Я Ваш, пример и использую. Данные о файле выдает исправно, а сами данные выдавать отказывается. Об ошибках не сообщает. Просто молчит... |
| Автор: Alexeis 27.4.2006, 14:49 |
| Black_Joker, Что возвращенный поток в себе ничего не содержит? Добавлено @ 14:58 Вот прикол размер данных проверил, а содержимое нет - и вправду там пусто! |
| Автор: Alexeis 27.4.2006, 15:31 |
| Я ошибся там совсем не пусто просто в начале тишина Вот Проект целиком посмотрите... http://alexei-s1.narod.ru/Wav.rar |
| Автор: Black_Joker 27.4.2006, 20:02 | ||
| Спасибо. Посмотрю. Большое спасибо. Не совсем понятно по поводу рисования. for i:= 1 to r.Data.Size div 4 do Begin r.Data.readBuffer(W1, 2); r.Data.readBuffer(W2, 2); Form1.Canvas.LineTo(round(100+2000/r.Data.Size*i), round(200+W1/100)); end; Считывается пара переменных, а почему используется только первая? Такая "форма сигнала" нормальная? - речь записанная с микофона. вывод:
|
| Автор: Black_Joker 3.5.2006, 11:32 |
| for i:= 1 to r.Data.Size div 4 do почему именно div 4 ? |
| Автор: Alexeis 3.5.2006, 11:50 |
| Я читаю данные фреймами. 1 фрейм 2 - канала по 2 байта в сэмпле каждого канала. 2х2=4 байта. Таким образом r.Data.Size div 4 дает нам именно число фреймов в блоке данных размером r.Data.Size. Для других данных размер фрейма будет другим... Добавлено @ 11:52 Размер фрейма можно вычислить по формуле FrSize := Round(wBitsPerSample / 8) * wChannels; |
| Автор: Black_Joker 3.5.2006, 20:23 |
| Понятно. Большое спасибо. а можно пояснить по поводу вопроса от 27.4.2006, 17:02 |
| Автор: Alexeis 4.5.2006, 10:15 | ||
Sorry не заметил поста.
Это был только пример кода демонстрирующий, что поток данных не пустой. А выводился только левый канал. Данный код ни в коем случае нельзя использовать в качестве образца! Он писался только чтоб отобразить именно этот фрагмет. А результат у вас получился плохой, только потому что моя методика слишком простая. Помните? частота дискретизации (в нашем случае частота пикелей) должна в два раза превышать частоту сигнала, иначе на изображении будут видны биения (они как раз и видны у вас, у меня их просто невидно, так как трек длиннее и сжатие графика выше). |
| Автор: Black_Joker 4.5.2006, 12:05 |
| Понятно. "Рисовать звук" мне не надо. Мне надо только получить данные. Надеюсь, на это пример способен? А то я уже собрался к начальнику идти... Очень не хрочется лохонуться. |
| Автор: Alexeis 4.5.2006, 12:14 |
| Если использовать в точности пример поста 27.4.2006, 17:02 то нет, там неправельно определен размер фрейма, а потому читается только половина файла, если заменить div 4, на div 2, то будет верно. |
| Автор: Black_Joker 5.5.2006, 08:53 |
| Не понял? Если 1 канала, то используем div 4, а если 1 канал используем div 2. Это я сделал. Чтоеще надо поправить? |
| Автор: Alexeis 5.5.2006, 09:46 |
Все больше ничего |
| Автор: Black_Joker 5.5.2006, 21:30 |
| Огромное спасибо за терпение и отзывчивость. Кто бы еще подсказал. как из этих данных частоту("ноты") выцепить... |
| Автор: Black_Joker 8.5.2006, 20:00 |
| Подскажите, пожалуйста, чем обоснован выбор именно SmallInt, а не Integer? мне нужно из одного звука "вычесть" второй. Считываю данные - W1 и W2 (массивы. звук одноканальный). Пишу W[i]:= abs(W1[i] - W2[i]); И получаю несколько отрицательных значений. Задал тип данных Integer. Все значения положительные, но очень большие - 9-и значные. Это нормально? |
| Автор: Black_Joker 11.5.2006, 09:32 |
| Массивы W, W1, W2 сперва были заданы типом СмолИнт. - при вычсислении W[i]:= abs(W1[i] - W2[i]); В массиве W[i] появлялись отрицательные значения. Задал дял массивов Интеджер - значеия в массива W - все положительные, но 9 значные. Вы предлагаете, использовать W1, W2 - СмолИнт, а W - Интеджер? |
| Автор: Alexeis 11.5.2006, 09:49 | ||
А что до сих пор не было отрицательных? Если данные 16 ти разрядные то волна должна переходить от плюса к минусу за период колебания. W точно должен быть integer ведь -32000 - (-32000) = -64000 - а это уже не поместится в smallInt |
| Автор: Black_Joker 17.5.2006, 10:20 |
| Подскажите, пожалуйста Считал 2 звука (в DataStrim: TStream) - 1-й поменьше - W1 2-й побольше - W2. 1. Что будет если из W2 отнять W1? Такое вобще возможно? 2. Во 2-м звуке может содержаться первый (может несколько раз или ни одного раза) Предполагается, что первый звук входит (если входит) без изменений во второй. Можно ли его найти (только средствами работы с DataStrim)? Как? |
| Автор: Alexeis 17.5.2006, 13:45 |
| Black_Joker, Разность это тоже что и сумма с перевернутым сигналом. Для того чтобы определить насколько один сигнал похож на другой необходимо провести операцию свертки. В качестве ядра свертки будет выступать первый сигнал. Свертка будет производится по второму сигналу. В результате мы получим масив длины равной разности втророго и первого, по значениям этого сигнала можно определить где именно появились повторения и насколько близки фрагмент второго и первый сигнал. Если они абсалютно подобны, то сигнал (массив) будет содержать несколько острых пиков, по числу появлений первого сигнала во втором. |