#delphi #sapi
Вопрос:
Я работаю с МИСС САПИ в Delphi7. Моя цель:
- проговорите список фраз в память
- получить количество байтов, занимаемых каждой фразой (для создания субтитров SRT)
- вывод данных из памяти в WAV-файл.
Все работает нормально, но я вижу, что каждая следующая фраза занимает больше времени, чем предыдущая (см. Скриншот). Я этого не понимаю. Есть ли какой-либо способ изменить это поведение?
uses ...SpeechLib_TLB...
procedure TForm1.Button2Click(Sender: TObject);
var
SpVoice: TSpVoice;
SpMemoryStream: TSpMemoryStream;
SpFileStream: TSpFileStream;
SavedCW: Word;
i: integer;
list: tstrings;
time1, time2, bytes1, bytes2: dword;
begin
ListBox1.Clear;
list:=tstringlist.create;
list.loadfromfile(extractfilepath(paramstr(0)) 'test1.txt');
SpVoice:=TSpVoice.create(nil);
SpMemoryStream:=TSpMemoryStream.Create(nil);
SpMemoryStream.Format.type_:=SAFT44kHz16BitMono;
SpVoice.AudioOutputStream:=SpMemoryStream.DefaultInterface;
SpFileStream:=TSpFilestream.Create(nil);
SpFileStream.Format.type_:=SAFT44kHz16BitMono;
SpFileStream.Open(ExtractFilePath(ParamStr(0)) 'test1.wav', SSFMCreateForWrite, FALSE);
SavedCW := Get8087CW;
Set8087CW(SavedCW or $4);
for i:=0 to list.count-1 do begin
time1:=gettickcount;
bytes1:=VarArrayHighBound(SpMemoryStream.GetData, 1);
SpVoice.Speak(list[i], 0);
time2:=gettickcount;
bytes2:=VarArrayHighBound(SpMemoryStream.GetData, 1);
ListBox1.items.Add(Format('%d ms %d Bytes %s', [time2-time1, bytes2-bytes1, list[i]]));
Label1.caption:=format('Item %d From %d', [i 1, list.count]);
Application.ProcessMessages;
end;
Set8087CW(SavedCW);
SpFileStream.Write(SpMemoryStream.GetData);
SpFileStream.Free;
SpMemoryStream.Free;
SpVoice.free;
list.free;
showmessage('All done');
end;
Комментарии:
1. Поскольку это поток , а не массив : каждый раз, когда он обрабатывается как массив , все его байты должны анализироваться с самого начала. Почему бы просто не использовать
.Seek( 0 )
, чтобы всегда проверять текущую позицию?2. @AmigoJack Я пробовал это: SpMemoryStream. Seek(0, SSSPTRelativeToStart); SpFileStream. Запись (SpMemoryStream. getData); после каждого выступления. Но этот способ приводит к повреждению файла WAV
3. Проблема не в проверке байтов, занятых вызовом VarArrayHighBound(SpMemoryStream . getData, 1); Даже если я удалю весь код, кроме SpVoice. Говорите (…) проблема остается.
4.
SSSPTRelativeToCurrentPosition
конечно: вы хотите получить текущую позицию, не меняя ее.5. @AmigoJack я понимаю, о чем ты говоришь. Ваше предложение позволяет получить количество байтов, не рассматривая поток как массив. Но я говорю о чем-то другом. Даже если я оставлю только . Произнесите (…) и удалите весь остальной код, каждая следующая фраза занимает все больше и больше времени. Это основная проблема.