Раздельная запись звука с левого и правого канала.
Модератор: Модераторы
- Kvasshtain
- новенький
- Сообщения: 13
- Зарегистрирован: 10.01.2011 15:25:49
Раздельная запись звука с левого и правого канала.
Народ! Вот тут еще вопрос возник. Есть вот тут такая статья http://www.delphikingdom.com/asp/viewit ... alogid=213 (правда она с вражеского сайта
) и там типа пишет человек, как звук записывать в wav файл. Так вот мне нуна отдельно писать правый канал, отдельно левый. Как это сделать?
Давным-давно я такое делал. Если я не ошибаюсь, в данных, которые приходят со звуковой карты, поочерёдно идут байты с правого и левого канала.
Т.е. один байт - правый канал, второй байт - левый и т.д.
Т.е. один байт - правый канал, второй байт - левый и т.д.
- Kvasshtain
- новенький
- Сообщения: 13
- Зарегистрирован: 10.01.2011 15:25:49
Спасибо за ответ.
Вы подтверждаете инфу, которую я уже потом нашел вот здесь http://kazus.ru/articles/52.html.
Но все таки, простите за тупость
, еще раз.
Т.е. я просто должен читать 16 бит (это в случае 8 битного стерео или 32 бита в случае 16 битного стерео) из wh1.lpData, а потом просто разделить их на две половинки, старшую и младшую, и все, хана
. Я правильно понял?
Вы подтверждаете инфу, которую я уже потом нашел вот здесь http://kazus.ru/articles/52.html.
Но все таки, простите за тупость
Т.е. я просто должен читать 16 бит (это в случае 8 битного стерео или 32 бита в случае 16 битного стерео) из wh1.lpData, а потом просто разделить их на две половинки, старшую и младшую, и все, хана
Все сводится к тому как вы получаете данные, тобишь в каком виде эти данные представлены. Если это стандартный Wav PCM, то там может быть и более 2-х каналов. Если это именно так, то скажем вот программка, которая может вам помочь разобраться как эти каналы записываются в формате Wav PCM.
Wave File Generator
Wave File Generator
- Kvasshtain
- новенький
- Сообщения: 13
- Зарегистрирован: 10.01.2011 15:25:49
Здорово Maxizar
, я тут много и долго плясал с бубном вокруг компа и вот чо накумекал
. То чо хранится в address^.lpData^ - это Char, т.е. byte, и в случае 8-и битного стерео тудой пишется то левый то правый канал. И получается, что отличить правый от левого со стороны посторонней подпрограммы невозможно (посторонней по отношению к procedure TformMain.MMProcData(var Message: TMessage), он же обработчик "данные готовы"). А внутри этой функции как я думаю мона сделать так, сказать что типа пускай @wh1 и @wh2 имеют размер по 8 бит, т.е. байт (ну понятно, что в случае 16 битного стерео, будет 16), тогда в @wh1, всегда будет левый, а в @wh2 правый сигналы, вот и все. Но я пока не пробовал. А вообще вопрос к гуру
. Нет ли в Waveform Audio Win32 API какой-нибудь функции, которая пишет каналы раздельно в разные места, что бы не городить весь этот огород
?
- Kvasshtain
- новенький
- Сообщения: 13
- Зарегистрирован: 10.01.2011 15:25:49
Добавлено спустя 5 минут 4 секунды:
Ну в 8-ми битном стерео у меня получилось писать данные с обоих каналов. Вот код:
Но как быть с 16 битами? Ведь в temp^.lpData^ лежит всегда только 8-бит, а для 16 битного стерео не понятно какой из 4-х байт относится к какому каналу и к какой половинке, старшей или младшей.
Т.е. я не пойму:
толи сначала младшая половинка левого, потом старшая половинка левого, потом младшая половинка правого, потом старшая половинка правого,
толи сначала младшая половинка левого, потом младшая половинка правого, потом старшая половинка левого, потом старшая половинка правого,
или вообще еще как-нибудь?
И как потом все это хозяйство правильно раздельно прочитать, а потом правильно сшить воедино?
Вот моя гипотеза, которая не работает:
[/code]
Ну вот собственно и усо.
Ну в 8-ми битном стерео у меня получилось писать данные с обоих каналов. Вот код:
Код: Выделить всё
// обработчик "данные готовы"
procedure TformMain.MMProcData(var Message: TMessage);
var
temp: pWaveHdr;
recorded: integer;
begin
temp:=address;
if address=@wh1 then address:=@wh2 else address:=@wh1;
// если не остановлено, ставим в очередь
if not stop then
waveInAddBuffer(hwi,address,sizeof(TWaveHdr));
recorded:=address.dwBytesRecorded;
// записываем блок
BlockWrite(fOut,(temp.lpData)^,recorded);
if (address.dwBufferLength=1) and (formMain.Channels=2) then //обработка стерео сигнала 8 бит
Begin
if address=@wh1 then
Begin
label2.Caption:=inttostr(ord(temp^.lpData^));
TrackBar1.Position:=ord(temp^.lpData^);
end
else
Begin
label3.Caption:=inttostr(ord(temp^.lpData^));
TrackBar2.Position:=ord(temp^.lpData^);
end;
end;
n:=n+recorded;
formMain.Label1.Caption:=IntToStr(n);
end;Но как быть с 16 битами? Ведь в temp^.lpData^ лежит всегда только 8-бит, а для 16 битного стерео не понятно какой из 4-х байт относится к какому каналу и к какой половинке, старшей или младшей.
Т.е. я не пойму:
толи сначала младшая половинка левого, потом старшая половинка левого, потом младшая половинка правого, потом старшая половинка правого,
толи сначала младшая половинка левого, потом младшая половинка правого, потом старшая половинка левого, потом старшая половинка правого,
или вообще еще как-нибудь?
И как потом все это хозяйство правильно раздельно прочитать, а потом правильно сшить воедино?
Вот моя гипотеза, которая не работает:
Код: Выделить всё
leftchanal:=true; //для случая 16 битного стерео сделать так как было для 8-и битного нельзя,
// там было так:
// в lpData^ всегда (для 8 и 16 бит) лежит 8 бит, и по этому в случае 8-и бит
// @wh1 всегда лежат данные левого канала, а в @wh2 данные правого канала
// Здесь же имеем следующее:
// Еще раз, в lpData^ всегда (для 8 и 16 бит) лежит 8 бит, но данные теперь 16-бит, а значит
// @wh1 всегда лежит младшая половинка (8-бит), а в @wh1 всегда лежит старшая половинка, но для
// нечетных пар @wh1 - @wh2 это данные левого канала, а для четных - данные правого.
// Флаг-переменная leftchanal - это флаг, установка которого в true значит, что сейчас очередь
// левого канала, и в начале мы его как раз и ставим в true, т.к. первая пара-нечетная, но
// в конце обработки пары мы должны опрокидывать этот флаг в противоположное состояние
if (address.dwBufferLength=2) and (formMain.Channels=2) then //обработка стерео сигнала 16 бит
Begin
if address=@wh1 then
Begin
loData:=ord(temp^.lpData^);
end
else
Begin
hiData:=ord(temp^.lpData^);
leftchanal:=not(leftchanal); // опрокидываем флаг
label3.Caption:=inttostr((hiData*256 + loData) div 256)
TrackBar2.Position:=hiData * 256 + loData) div 256;
end;
end;Ну вот собственно и усо.
