Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Media";
Текущий архив: 2008.03.16;
Скачать: [xml.tar.bz2];

Вниз

Проблемы с размером полученного wav   Найти похожие ветки 

 
Дмитрий (Гомель)   (2007-03-28 11:06) [0]

Итак, здравствуйте, господа-программисты. Совсем недавно решил при помощи инета задачу склеить несколько wav-файлов в один. Уже в конференции по Media об этом сообщал. Однако возникла проблема. Если, например файл из формата МР-2 перегоняют в wav, то при склеивании этого файла (даже если он один в блоке склеивания), при формировании заголовка и самого файла почему-то не сходится размер. Он меньше исходного на 34 байта по-моему. Точно надо посмотреть. Причем, есть подозрение, что не все прочитывается в заголовке wav-файла. У кого были похожие вопросы? Был бы благодарен за консультативную информацию.


 
wicked ©   (2007-03-28 11:59) [1]

а что говорит про это г-н Карапетян?


 
homm ©   (2007-03-28 12:03) [2]

> Он меньше исходного на 34 байта по-моему

Размер заголовка?


 
TRUNK ©   (2007-03-28 12:12) [3]

Это всё из-за того, что некорректно обрабатывется структура файла. Долго наблюдал за соседней веткой (какой именно - думаю говорить не стоит), но так никто ничего и не поправил. Похоже, что придётся это сделать мне :). Во-первых, заголовки в RIFF файле читать надо по-отдельности, а не одним блоком, т.к. не факт, что они будут идти именно в такой последовательности. Во-вторых, размер RiffLen для конечного файла определяется некорректно. В-третьих, в файле могут быть и другие секции данных, которые тоже нужно учитывать.


 
wicked ©   (2007-03-28 12:18) [4]

> TRUNK ©   (28.03.07 12:12) [3]
поправил...
только вместо рыбы я дал человеку удочку

отсюда и мой первый постинг - пусть ответит на вопрос :)


 
wicked ©   (2007-03-28 12:22) [5]

добавлю, что WAVEFORMATEX очень часто бывает частью другого заголовка
какого именно - определяется полями wFormatTag и cbSize

но подождем, что скажет г-н Карапетян ;)


 
TRUNK ©   (2007-03-28 12:32) [6]

> wicked ©   (28.03.07 12:22) [5]
> но подождем, что скажет г-н Карапетян ;)

Может я чего недочитал, но если не секрет, кто такой Карапетян ?


 
wicked ©   (2007-03-28 12:42) [7]

> TRUNK ©   (28.03.07 12:32) [6]

>
> > wicked ©   (28.03.07 12:22) [5]
> > но подождем, что скажет г-н Карапетян ;)
>
> Может я чего недочитал, но если не секрет, кто такой Карапетян
> ?

упоминается он там - http://delphimaster.net/view/8-1174370882/

а кто он?... не знаю, авторитет какой то, у автора надо спрашивать :)


 
Дмитрий (Гомель)   (2007-03-29 11:50) [8]

Привет, народ! Ну навалились все разом! Ладно уже распинать :-). Ну бывают траблы. Кто ничего не делает - тот и не ошибается. Согласен. Обработку заголовка файла вел лишь по определенной схеме. Каких-то вещей не знаю. Скребу инет в поисках "утраченного". Про авторитет - человек предложил схему, я ее использовал. Работало. Теперь получил другие файлы. Увы... Вот и вопрос. Как мне обработать все заголовки, заранее не зная в какой они идут последовательности. Тема для меня все-таки новая, но разобраться хочу. Размер Rifflen? Уже согласен. Определяется не так как в первый раз (в исходном коде). Как учесть другие секции данных? Каков метод?


 
TRUNK ©   (2007-03-29 14:07) [9]

На первый и третий вопросы (Как обработать все заголовки и Как учесть другие секции данных) одно решение - при их поиске пользоваться именами, находящимися в заголовках секций (те самые "fmt " и "data"). Другими словами, нужно прочитать имя первой секции и её размер. Если имя секции не то которое нас интересует или вообще неизвестное, увеличиваем файловый указатель на размер секции, тем самым переходя на начало следующей секции (либо в конец файла). Если же имя подходит - читаем данные из этой секции. Далее повторяем тоже самое пока не будут найдены все интересующие данные. Алгоритм очень простой. Что же касается Rifflen, то, в подавляющем большинстве случаев, она равна FileSize-8.


 
Дмитрий (Гомель)   (2007-03-29 17:15) [10]

Ок. Таким образом мы переходим к следующей ступени. Я ищу скажем так ключевые слова: Wave, Riff, fmt, data. Тогда вопрос, каков размер каждой секции? Секции имеют фиксированный размер?Т.е. я понимаю ситуация такова - я начинаю читать файл по байтам или по фиксированному размеру, например 4? чтобы попасть в нужный размер? что есть точка отсчета? хотя мне кажется я уже понимаю.


 
wicked ©   (2007-03-29 17:24) [11]

повторю еще раз - взяться и почитать об mmioOpen/mmioClose, mmioAscend/mmioDescend, mmioRead/mmioWrite - все уже написано и не надо "искать ключевые слова"


 
Дмитрий (Гомель)   (2007-03-29 17:34) [12]

Ну что же, я почитаю обязательно. А чем это интереснее? потому что API? Если где-то ошибся прошу извинить.


 
TRUNK ©   (2007-03-30 10:23) [13]

> Дмитрий (Гомель)   (29.03.07 17:15) [10]

Секция устроена так: сначала идут 4 байта с именем, затем 4 байта с размером данных, затем идут данные этой секции, т.е. условно так:
ChunkName: array[0..3] of Char;
ChunkSize: Cardinal;
ChunkData: ...; // размер равен ChunkSize
Размер всей секции, следовательно, равен ChunkSize+8.
Существует ещё один вид секций - это секции-контейнеры, которые могут содержать в себе другие секции. Таких секций-контейнеров пока всего два вида - это LIST и RIFF. Их формат отличается тем, что первые четыре байта данных указывают тип содержимого секции-контейнера. Например, в нашем случае у секции RIFF тип содержимого WAVE.

> Я ищу скажем так ключевые слова: Wave, Riff, fmt, data

Как, наверное, уже стало понятно, WAVE искать не надо - его надо проверять. RIFF искать тоже не надо - нужно просто в самом начале проверить, что первые четыре байта файла равны RIFF. Искать в нашем случае надо только fmt и data.

P.S. Если всё-равно будет непонятно, могу кинуть на мыло пример объединения WAV-файлов.


 
Дмитрий (Гомель)   (2007-03-30 17:15) [14]

Спасибо, TRUNK. Пока сам поковыряю. Если можно - буду по мере формирования кода демонстрировать в ветке? Комментарии конечно будут нужны. Главное что стало понятно следующее - непостоянная структура wav. Ну извините, что так? Спасибо, парни. Еще появлюсь.


 
Дмитрий (Гомель)   (2007-04-13 18:58) [15]

Привет, народ. Вот я и появился вновь. Все работает - склеивает файлы PCM формата 16 Bit и с частотой 44100. Вот код чтения:

function ReadWaveHeader(FileName:String;F:TFileStream):TWaveHeader;
var
    WaveHeader:TWaveHeader;
    DataChunk:      String[4];
    Name:           TFileStream;
    Pos:            Integer;
    Data:           PChar;
    DataSize:       DWord;
{     ChunkID:        Array[0..3] of Char; {метка "RIFF"}
{     ChunkIDSize:    LongInt;             {размер "Rifflen"}
{     FormatPCM:      Array[0..3] of Char; {метка "WAVE"}
{     SubChunk1ID:    Array[0..3] of Char; {метка "fmt_"}
{     SubChunk1IDSize:LongInt;             {размер "fmt_"}
{     AudioFormatPCM: Word;                {метка формата PCM, если "1", то все в порядке}
{     NumChannels:    Word;                {количество каналов, 2 - стерео, 1-моно}
{     SampleRate:     LongInt;             {частота - 44100 Гц}
{     BytesPerSecond: LongInt;             {}
{     BlockAlign:     Word;                {}
{     BitsPerSample:  Word;                {16 bit}
{     SubChunk2ID:    Array[0..3] of Char; {метка "data"}
{    SubChunk2Size:  LongInt;      }

begin
Name:=TFileStream.Create(FileName,fmOpenRead);
Pos:=0;
SetLength(DataChunk,4);
repeat
 Name.Seek(Pos, soFromBeginning);
 Name.Read(DataChunk[1],4);
 if DataChunk="RIFF" then
 begin
 WaveHeader.ChunkID:="RIFF";
 Name.Read(WaveHeader.ChunkIDSize,4);
 end;
 if DataChunk="WAVE" then
 begin
 WaveHeader.FormatPCM:="WAVE";
 end;
 if DataChunk="fmt " then
 begin
 WaveHeader.SubChunk1ID:="fmt ";
 Name.Read(WaveHeader.SubChunk1IDSize,4);
 Name.Read(WaveHeader.AudioFormatPCM,2);
 Name.Read(WaveHeader.NumChannels,2);
 Name.Read(WaveHeader.SampleRate,4);
 end;
 Inc(Pos);
until DataChunk = "data";
if (WaveHeader.ChunkID<>"RIFF") or (WaveHeader.FormatPCM<>"WAVE") or (WaveHeader.SubChunk1ID<>"fmt ") or (WaveHeader.AudioFormatPCM<>1)
then
showmessage("Invalid wav-mediafile");
WaveHeader.SubChunk2ID:="data";
Name.Read(WaveHeader.SubChunk2Size,4);
Pos:=Name.Position;
Name.Seek(Pos-4,soFromBeginning);
Name.Read(DataSize, Sizeof(DWORD));
GetMem(Data,DataSize);
Name.Read(Data^,DataSize);
F.Seek(0,soFromEnd);
F.Write(Data^,DataSize);
FreeMem(Data,DataSize);
Name.Free;
Result:=WaveHeader;
end;

Несколько комментариев. Я читаю заголовок, отделяю тело и получаю готовый материал.

Процедура формирования заголовка и итогового файла такова:

procedure CreateWaveHeader(FTemp:String;FB:TFileStream);
var
MF:TFileStream;
begin
MF:=TFileStream.Create(FTemp,fmOpenRead);
WaveF.ChunkID:="RIFF";
WaveF.ChunkIDSize:=MF.Size+36;
WaveF.FormatPCM:="WAVE";
WaveF.SubChunk1ID:="fmt ";
WaveF.SubChunk1IDSize:=16;
WaveF.AudioFormatPCM:=1;
WaveF.NumChannels:=2;
WaveF.SampleRate:=44100;
WaveF.BytesPerSecond:=WaveF.SampleRate*WaveF.NumChannels;
WaveF.BitsPerSample:=16;
WaveF.SubChunk2ID:="data";
WaveF.SubChunk2Size:=MF.Size;
FB.Write(waveF,sizeof(waveF));
FB.copyfrom(MF,MF.Size);
MF.Free;
.......

Полученные файлы читаются, играются. В общем все четко. Но один нюанс. При перегоне формата моего полученного файла в другой в старый формат MP-2 (кодек QDesign) выскакивает сообщение "Ошибка инициализации аудио обработки". Что я не дописываю в файл или что делаю неверно? Заранее спасибо.


 
TRUNK ©   (2007-04-16 15:41) [16]

Создание заголовка надо изменить так:

//...........................
WaveF.AudioFormatPCM := 1;
WaveF.NumChannels := 2;
WaveF.SampleRate := 44100;
WaveF.BitsPerSample := 16;
WaveF.BlockAlign := (WaveF.BitsPerSample div 8)*WaveF.NumChannels;
WaveF.BytesPerSecond := WaveF.SampleRate*WaveF.BlockAlign;
//...........................


 
Дмитрий (Гомель)   (2007-04-21 11:22) [17]

TRUNK. Спасибо. Вот залез на ветку опять - не оставили без внимания. Но сам уже разобрался. Немного невнимателен был. Все получилось. Отлично. Теперь думаю, как конвертер написать для других файлов, например с другой частоткой (48 kHZ, mp3 и т.д.). Соответственно кодек использовать для этого Lame (как вариант). В какую сторону копать? Т.е. я хочу, чтобы программа детектила файл, определяла его формат и сама конвертила в простой PCM?



Страницы: 1 вся ветка

Форум: "Media";
Текущий архив: 2008.03.16;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.006 c
15-1202471403
oxffff
2008-02-08 14:50
2008.03.16
Еду в командировку в Пермь. Было бы здорово встретиться


2-1203079733
SerMaxx
2008-02-15 15:48
2008.03.16
использование DBGrid или Grid


2-1203455145
{RASkov}
2008-02-20 00:05
2008.03.16
MessageBox + MB_HELP


15-1202221266
Пробегал...
2008-02-05 17:21
2008.03.16
RegisterServiceCtrlHandlerEx в win9x?


3-1193207750
AlexeyMir
2007-10-24 10:35
2008.03.16
Троеточие в ячейке DBGrida





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский