Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Звук, графика и видео > Использование TAPRO


Автор: unreg 4.11.2004, 11:16
Здравствуйте.
Установил себе компоненты turbo async professional 4.06. Нужны для моего автоответчика. ОС winxp sp2. для передачи/приема звук. файла/голоса в звук файл, попытался использовать компонент TApdTapiDevice. компонент заругался, что не тот SAPI установлен. Скачал "тот" (SAPI4.0) все пошло нормально. Я могу записывать звук из линии и проигрывать звук в линию (!).
Решил пойти дальше. С помощью голосового движка прочитать в линию какой-нибудь текст. Для этого используются компоненты TApdSapiEngine и TApdSapiPhone. Снова компоненты заругались, что не могут инициализировать некий интерфейс. нашел строчку в AdSapiEn.pas и заремил вызов процедуры InitializeSR. (компонент не мог инициализировать DirectSR, хотя он у меня есть, да и бог с ним). Ругаться компонент перестал.

Все это написано для тех кому не хочется наступать на теже грабли, что и я.

А теперь, собственно, проблема. При попытке инициализировать голос в линию, опять маты в мою сторону. Примерно такие: движок не оптимизирован для передачи звука в телефонную линию. Т.е. он бы и рад, да не может (формат не позволяет).
Я снова покопался в исходника компонентов и нашел флаг который сигнализирует о том оптимизирован голос для телефона или нет. В системе у меня стоит 5 голосовых движков Digalo, и 4 штуки от Lernout&... (муж. жен./англ. рус.), перепробовал все. и ни один не подходит получается???
Кто-нибудь сталкивался с подобной проблемой????

спасибо.

PS есть вариант записывать текст в вав-файл. Это у TApdSapiEngine получается здорово. Но нужен конвертер который из этой вав-ки сделает другую вав-ку но с более низким качеством (8 кГц, 16 бит, Моно) и естественно у конвертера должна быть возможность управляться програмно (как ком-объект или из командной строки или еще как). Я такого конвертера не знаю.

Автор: p0s0l 4.11.2004, 14:40
Если wav'ы пишутся в формате PCM (без сжатия), то довольно просто будет вручную сконвертить...

Автор: unreg 4.11.2004, 17:17
Да, пишет в PCM. А как сконвертировать ? smile

Автор: p0s0l 5.11.2004, 02:03
Накидал примерно как это должно быть...
Но... Блин, не могу нормально понизить BitsPerSample (с 16 бит на 8). Получается какая-то бяка...
Щас сделано так: если входной файл имеет 16-битные данные, то берутся 8 старших бит данных (младшие теряются)... Видимо надо другой алгоритм... Подумай, как надо правильно... (смотри SetV)
Код
procedure ConvertPCM (const OldFile, NewFile : string; khz, bits, ch : integer);
type
 PChunk = ^TChunk;
 TChunk = array [0..3] of char;

var
 Buf, NewData : Pointer;
 BufSize, MaxAdr, NewBlockAlign, NewDataSize : DWORD;
 f : file;
 wf : PPCMWAVEFORMAT;
 Adr, AdrData, AdrNew, DataSize, i, Sample, Samples, NewSamples : DWORD;
 k : real;
 bNew, leftbits : byte;
 v1, v2 : integer;

 WavHdr : record
   Riff : TChunk;
   RiffSize : DWORD;
   RiffType : TChunk;
   ckFmt : TChunk;
   ckFmtSize : DWORD;
   format : PCMWAVEFORMAT;
   ckData : TChunk;
   ckDataSize : DWORD;
 end;

 function FindChunk (Chunk : TChunk) : Pointer;
 var
   Adr : DWORD;
 begin
   Result := nil;
   Adr := DWORD(Buf)+12;
   while PChunk(Adr)^ <> Chunk do
   begin
     Inc (Adr, PDWORD(Adr+4)^ + 8);
     if Adr >= MaxAdr then Exit;
   end;
   Result := Pointer(Adr + 8);
 end;

 function GetV : integer;
 begin
   if wf.wBitsPerSample = 8 then
   begin
     Result := PByte(Adr)^;
     Inc(Adr);
   end
   else
   begin
     Result := PWord(Adr)^;
     Inc(Adr, 2);
   end;
 end;

 procedure SetV (v : integer);
 begin
   v := v shr leftbits;
   if bits = 8 then
   begin
     PByte(AdrNew)^ := Byte(v);
     Inc(AdrNew);
   end
   else
   begin
     PWord(AdrNew)^ := Word(v);
     Inc(AdrNew, 2);
   end;
 end;

begin
 AssignFile (f, OldFile);
 Reset (f, 1);
 BufSize := FileSize(f);
 GetMem (Buf, BufSize);
 BlockRead (f, Buf^, BufSize);
 CloseFile (f);

 MaxAdr := DWORD(Buf) + BufSize;
 Pointer(wf) := FindChunk ('fmt ');

 AdrData := DWORD(FindChunk ('data'));
 DataSize := PDWORD(AdrData-4)^;
 Samples := DataSize div wf.wf.nBlockAlign;

 k := khz / wf.wf.nSamplesPerSec;
 NewSamples := Trunc(Samples * k);

 bNew := bits div 8;
 NewBlockAlign := bnew*ch;
 NewDataSize := NewSamples * NewBlockAlign;
 GetMem (NewData, NewDataSize);
 AdrNew := DWORD(NewData);

 leftbits := 0;
 if bits < wf.wBitsPerSample then leftbits := wf.wBitsPerSample - bits;

 if NewSamples > 0 then
   for i := 0 to NewSamples-1 do
   begin
     Sample := Trunc(i/k);
     Adr := AdrData + (Sample * wf.wf.nBlockAlign);
     v1 := GetV;
     if wf.wf.nChannels = 2 then v2 := GetV;
     SetV(v1);
     if ch = 2 then SetV(v2);
   end;

 AssignFile (f, NewFile);
 Rewrite (f, 1);
 WavHdr.Riff := 'RIFF';
 WavHdr.RiffSize := SizeOf(WavHdr)-8 + NewDataSize;
 WavHdr.RiffType := 'WAVE';
 WavHdr.ckFmt := 'fmt ';
 WavHdr.ckFmtSize := SizeOf(WavHdr.format);
 WavHdr.format.wf.wFormatTag := WAVE_FORMAT_PCM;
 WavHdr.format.wf.nChannels := ch;
 WavHdr.format.wf.nSamplesPerSec := khz;
 WavHdr.format.wf.nAvgBytesPerSec := khz * NewBlockAlign;
 WavHdr.format.wf.nBlockAlign := NewBlockAlign;
 WavHdr.format.wBitsPerSample := bits;
 WavHdr.ckData := 'data';
 WavHdr.ckDataSize := NewDataSize;

 BlockWrite (f, WavHdr, SizeOf(WavHdr));
 BlockWrite (f, NewData^, NewDataSize);

 CloseFile (f);

 FreeMem (NewData);
 FreeMem (Buf);
end;

Пример:
Код
 ConvertPCM ('c:\windows\media\notify.wav', 'c:\3.wav', 11025, 16, 1);

PS: пробовал через MCI менять формат - не получилось smile
Хотя есть команда MCI_SET, и в MSDN сказано:
Цитата(MSDN)
MCI_WAVE_SET_SAMPLESPERSEC
Sets the samples per second used for playing, recording, and saving to the nSamplesPerSec member of the structure identified by lpSet.
Т.е. можно менять параметры для проигрывания, записи и сохранения...

Автор: unreg 5.11.2004, 06:20
Спасибо. Код работает. Ковнертирует без проблем, буду пользоваться. Спасибо еще раз. Найду время, обязательно поковыряюсь с API. Кстати, в поисках решения краем глаза зацепил функции семейства ACM... ими, вроде, тоже можно конвертировать.

Автор: Medved 6.11.2004, 16:04
Кстати, когда -то давно приводили исходник работы с голосвым движком от Mircosoft. Воспользуйтесь поиском.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)