Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.191.132.194] |
|
Сообщ.
#1
,
|
|
|
В общем есть бесконечный цикл, в котором не прерывно пишется в поток SoundMEM, получается его крусор всегда в конце так как данные дописываются.
я хотел в ПОТОКЕ откопировать часть данных из SoundMEM , длинной к примеру с 5 по 74 позицию, для дальнейшей обработки, но как же мне это сделать если курсор постоянно движется? если я поставлю курсор SoundMEM на 5 позицию в потоке то данные запишутся по верх. что делать? хотел осуществить непрерывную запись и обработку результатов в потоке. form1.FLACOut1.Stream:=SoundMEM; //указываем поток в который писать form1.FLACOut1.Run; //запускаем запись в формат FLAC в поток while True do begin sleep(1000); //пауза секунда //единица расчета application.ProcessMessages; //даем немного процессорного времени что бы войти в поток T1 := TMyThread.Create(false); //создаем поток и сразу запускаем его //этот поток формирует пакет flac с заголовком размером в 2 секунды //и отправляет в гугл на распознание //затем результаты добавляет в базу данных MYSQL //сама программа дальше продолжает работу end; |
Сообщ.
#2
,
|
|
|
Цитата Emmys @ что делать? Прочитай про свойство TMemoryStream.Memory. Которое, внезапно, указатель. Подумай, на что он указывает и как это можно использовать в контексте вот этого: Цитата Emmys @ если я поставлю курсор SoundMEM на 5 позицию в потоке то данные запишутся по верх |
Сообщ.
#3
,
|
|
|
Блин не догоняю что хочешь сказать ты.
property Memory: Pointer; определяет область памяти, отведенную для хранения данных потока. Изменение размера отведенной памяти осуществляется методом |
Сообщ.
#4
,
|
|
|
Цитата Emmys @ Блин не догоняю что хочешь сказать ты Только то, что ты легко можешь организовать буфер и скопировать туда данные, начиная c указателя Memory потока, количеством, не превышающим Size потока включительно. Совершенно не задействовав методы чтения самого потока и не трогая указатель потока методом Seek. И эти данные будут соответствовать данным, которые находятся в самом потоке. |
Сообщ.
#5
,
|
|
|
и вообще не понятно через 2 прохода потока, при входе на 3й поток исполнение самой программы в потоке теряется.
исходники тут http://fsdbhome.ru/forum/GoogleSend_v4.0.rar unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ACS_Classes, ACS_DXAudio, ACS_Streams, StdCtrls, Buttons, ACS_Wave, ExtCtrls, ACS_FLAC, IdBaseComponent, IdAntiFreezeBase, IdAntiFreeze; type TMyThread = class(TThread) private { Private declarations } protected procedure OnTheardProcessRun; procedure Execute; override; end; type TForm1 = class(TForm) FLACOut1: TFLACOut; DXAudioIn1: TDXAudioIn; Panel1: TPanel; Panel2: TPanel; IdAntiFreeze1: TIdAntiFreeze; procedure FormCreate(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); private { Private declarations } public { Public declarations } SoundMEM:TMemoryStream; //Аудио поток flac SoundStart:int64; //стартовая позиция записи SoundStop:int64; //конечная позиция записи SoundWaitTheard:boolean; //ждем когда старт и стоп отработают и только тогда новые даем ProxyUse:string; //используем прокси =[no] или [yes] ProxyServer:string; //прокси сервер ProxyPort:string; //прокси порт ProxyUsername:string; //прокси пользователь ProxyPassword:string; //прокси пароль TimePos:Tstringlist; T1 : TMyThread; //объявляем поток end; var Form1: TForm1; implementation {$R *.dfm} procedure TMyThread.Execute; begin Synchronize(OnTheardProcessRun); end; procedure TMyThread.OnTheardProcessRun; var s:string; h:integer; SoundHandleMEM:TMemoryStream; //Заголовок flac файла SoundCopyMEM:TMemoryStream; begin //начинаем формирование заголовка flac файла SoundHandleMEM:=TMemoryStream.Create; SoundHandleMEM.Position:=0; SetLength(s,74); s[1]:=chr(102); s[2]:=chr(76); s[3]:=chr(97); s[4]:=chr(67); s[5]:=chr(0); s[6]:=chr(0); s[7]:=chr(0); s[8]:=chr(34); s[9]:=chr(18); s[10]:=chr(0); s[11]:=chr(18); s[12]:=chr(0); s[13]:=chr(0); s[14]:=chr(12); s[15]:=chr(108); s[16]:=chr(0); s[17]:=chr(16); s[18]:=chr(167); s[19]:=chr(1); s[20]:=chr(244); s[21]:=chr(0); s[22]:=chr(240); s[23]:=chr(0); s[24]:=chr(1); s[25]:=chr(68); s[26]:=chr(0); s[27]:=chr(193); s[28]:=chr(76); s[29]:=chr(208); s[30]:=chr(168); s[31]:=chr(87); s[32]:=chr(5); s[33]:=chr(147); s[34]:=chr(73); s[35]:=chr(141); s[36]:=chr(190); s[37]:=chr(25); s[38]:=chr(191); s[39]:=chr(124); s[40]:=chr(247); s[41]:=chr(175); s[42]:=chr(128); s[43]:=chr(132); s[44]:=chr(0); s[45]:=chr(0); s[46]:=chr(21); s[47]:=chr(13); s[48]:=chr(0); s[49]:=chr(0); s[50]:=chr(0); s[51]:=chr(86); s[52]:=chr(69); s[53]:=chr(78); s[54]:=chr(68); s[55]:=chr(79); s[56]:=chr(82); s[57]:=chr(61); s[58]:=chr(72); s[59]:=chr(97); s[60]:=chr(99); s[61]:=chr(107); s[62]:=chr(101); s[63]:=chr(100); s[64]:=chr(0); s[65]:=chr(0); s[66]:=chr(0); s[67]:=chr(0); s[68]:=chr(255); s[69]:=chr(248); s[70]:=chr(84); s[71]:=chr(8); s[72]:=chr(0); s[73]:=chr(173); s[74]:=chr(18); for h := 1 to Length(s) do SoundHandleMEM.Write(s[h], 1); //формирует заголовок flac файла в 10 секунд //формируем заголовок файла FLAC в 10 секунд //хотя реальные аудио данные будут всего на 2 секунды //но гугл поймет правильно, а мы сделали так, что бы //случайно не зарезать данные , ведь заголовок FLAC все равно //частично не валидный SoundHandleMEM.Position:=SoundHandleMEM.Size; //в самый конец ставим курсор, что бы дописать аудио данные //продолжительностью 2 секунды SoundCopyMEM:=TMemoryStream.Create; SoundCopyMEM.Position:=0; SetLength(s,form1.SoundStop-form1.SoundStart); form1.SoundMEM.Position:=0; Move(form1.SoundMEM.Memory^, s[1],form1.SoundMEM.Size); form1.SoundMEM.Position:=form1.SoundMEM.Size; //норм работает h := form1.SoundStart; while h<=form1.SoundStop do begin SoundHandleMEM.Write(s[h], 1); inc(h); application.ProcessMessages; end; //if SoundHandleMEM.Size=123213 then exit; //if form1.SoundMEM.Size=123213 then exit; //устанавливаем курсор в теле данн..ых SoundMEM //на позицию, которая была концом 2 секунды назад //т.е. мы указали на какой позиции был курсор 2 секунды назад, //что бы выдрать кусочек аудио данных за 2 секунды SoundHandleMEM.SaveToFile('E:\test\'+inttostr(random(999999999))+'.flac'); SoundHandleMEM.Free; form1.SoundWaitTheard:=false; //не ждать больше запуска другого потока //прекратить борьбу потоков за ресурс //form1.SoundStop и form1.SoundStart end; procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin SoundMEM.Free; //освобождаем память end; procedure TForm1.FormCreate(Sender: TObject); var cmd,tmp1:string; v,c:integer; begin randomize; application.ShowMainForm:=false; //скрываем форму в любом случае cmd:=windows.GetCommandLine; cmd:='-record "1" -ProxyUse "[no]" -ProxyServer "10.41.64.21" -ProxyPort "0" -ProxyUsername "alukyanov" -ProxyPassword "a*123456"'; if pos('-record "',cmd)=0 then begin application.Terminate; halt(0); exit; end; //прерываем если этого параметра не передали программе if pos('-ProxyUse "',cmd)=0 then begin application.Terminate; halt(0); exit; end; //прерываем если этого параметра не передали программе if pos('-ProxyServer "',cmd)=0 then begin application.Terminate; halt(0); exit; end; //прерываем если этого параметра не передали программе if pos('-ProxyPort "',cmd)=0 then begin application.Terminate; halt(0); exit; end; //прерываем если этого параметра не передали программе if pos('-ProxyUsername "',cmd)=0 then begin application.Terminate; halt(0); exit; end; //прерываем если этого параметра не передали программе if pos('-ProxyPassword "',cmd)=0 then begin application.Terminate; halt(0); exit; end; //прерываем если этого параметра не передали программе tmp1:=cmd; delete(tmp1,1,pos('-record "',tmp1)+length('-record "')-1); delete(tmp1,pos('"',tmp1),length(tmp1)); val(tmp1,v,c); if (v<=0) or (v+1>form1.DXAudioIn1.DeviceCount) or (c<>0) then begin application.Terminate; halt(0); exit; end; //если номер микрофона не верный то закрыть программу form1.DXAudioIn1.DeviceNumber:=v; //указываем микрофон с которого записывать tmp1:=cmd; delete(tmp1,1,pos('-ProxyUse "',tmp1)+length('-ProxyUse "')-1); delete(tmp1,pos('"',tmp1),length(tmp1)); form1.ProxyUse:=tmp1; //используем прокси =[no] или [yes] tmp1:=cmd; delete(tmp1,1,pos('-ProxyServer "',tmp1)+length('-ProxyServer "')-1); delete(tmp1,pos('"',tmp1),length(tmp1)); form1.ProxyServer:=tmp1; //прокси сервер tmp1:=cmd; delete(tmp1,1,pos('-ProxyPort "',tmp1)+length('-ProxyPort "')-1); delete(tmp1,pos('"',tmp1),length(tmp1)); val(tmp1,v,c); if (v<0) or (c<>0) then begin application.Terminate; halt(0); exit; end; //если это не число, то прерываем form1.ProxyPort:=tmp1; //прокси порт tmp1:=cmd; delete(tmp1,1,pos('-ProxyUsername "',tmp1)+length('-ProxyUsername "')-1); delete(tmp1,pos('"',tmp1),length(tmp1)); form1.ProxyUsername:=tmp1; //прокси пользователь tmp1:=cmd; delete(tmp1,1,pos('-ProxyPassword "',tmp1)+length('-ProxyPassword "')-1); delete(tmp1,pos('"',tmp1),length(tmp1)); form1.ProxyPassword:=tmp1; //прокси пароль form1.SoundMEM:=TMemoryStream.Create; //создаем поток с аудиоданными form1.FLACOut1.Stream:=SoundMEM; //указываем поток в который писать form1.TimePos:=Tstringlist.Create; //создаем хронологичесикий массив //каждую секунду отмеривает позицию form1.TimePos.Clear; form1.FLACOut1.Run; //запускаем запись в формат FLAC в поток //CreateHandleFlac10sec; //формируем заголовок в 10 секунд form1.SoundMEM.Position:=0; //курсор в памяти на начало form1.TimePos.Add('0'); //стартовое значение sleep(1000); //сдвигаемся по ремени, что бы были данные начальные //в цикле уже за 2 секунды form1.TimePos.Add(inttostr(form1.SoundMEM.Size)); //самый конец узнаем каждую секунду SoundWaitTheard:=false; //чуть чуть подождать в потоке запущеном while True do begin sleep(100); //пауза секунда //единица расчета form1.TimePos.Add(inttostr(form1.SoundMEM.Size)); //самый конец узнаем каждую секунду while form1.SoundWaitTheard=true do begin application.ProcessMessages; sleep(100); end; //ждем мы совсем чуть чуть, а может и вовсе не ждем //на всякий случай что бы не было багов в процессе возможной борьбы потоков SoundWaitTheard:=true; //чуть чуть подождать в потоке form1.SoundStart:=strtoint64(form1.TimePos.Strings[form1.TimePos.Count-3]); form1.SoundStop:=strtoint64(form1.TimePos.Strings[form1.TimePos.Count-1]); application.ProcessMessages; //даем немного процессорного времени что бы войти в поток t1:=TMyThread.Create(false); //создаем поток и сразу запускаем его //этот поток формирует пакет flac с заголовком размером в 2 секунды //и отправляет в гугл на распознание //затем результаты добавляет в базу данных MYSQL //сама программа дальше продолжает работу end; end; end. |
Сообщ.
#6
,
|
|
|
Цитата Emmys @ если я поставлю курсор SoundMEM на 5 позицию в потоке то данные запишутся по верх. что делать? хотел осуществить непрерывную запись и обработку результатов в потоке. Ну и в чем проблема? Без межпоточной синхронизации TMemStream с наращиваемым размером по любому нельзя использовать. Ну а если есть Synchronize, то нет проблемы передвигать Position кому-куда требуется. Добавь перед записью Seek(0,soFromEnd) и всё |
Сообщ.
#7
,
|
|
|
Нет никакой гарантии, что сам компонент FlacOUT использует метод Synchronize, он пишет постоянно. туда сюда курсор дергать ведь не получится наверное и я не понял что вы хотели скачать. мне по подробнее пишите, я не сильно разбираюсь
Добавлено пытался придерживаться вот этой схемы http://fsdbhome.ru/foto/flac.jpg |
Сообщ.
#8
,
|
|
|
Цитата Emmys @ Нет никакой гарантии, что сам компонент FlacOUT использует метод Synchronize, он пишет постоянно Тогда вообще забудь о каком-либо обращении к TMemStream, в который происходит запись в другом thread, иначе можешь нарваться на Access Violation. Тут остается либо ждать окончания записи, либо, если это возможно, дробить запись на отдельные части\блоки - заканчиваем запись в один блок, отдаем его (тем или иным образом) главному потоку и начинаем запись в новый блок и т.д. Ну или использовать кольцевой буфер достаточно большого, но ФИКСИРОВАННОГО размера - если доходим до конца (Size), то начинаем запись с начала (Position:=0). Но это опять же - если позволяет твой FlacOUT |
Сообщ.
#9
,
|
|
|
да, после 2-3го прохода уже сразу получаю Access Violation....
кольцевой буфер - это цель, но его смысл теряется если я буду использовать старые данные. я вас понял, взять и записать 1 минуту например и ковыряйся в потоке потоке сколько хочешь = пока новый пишется. дели и так далее. но я хочу прямо сейчас ковырятся хочу в каждую новую секунду, получать последние 2 секунды записи и делать с ними что угодно Добавлено кое что начало получаться. предварительно. была ошибка в коде логическая. тестирую... |
Сообщ.
#10
,
|
|
|
medved_68, теперь понял так и сделал - заработало. еще тестирую. спасибо большое
Добавлено кажется получилось Поочередно надиктовывал цифры. записи отправлялись последние 2 секунды записи, через каждую секунду. т.е. в перехлест согласно схеме которую выкладывал. ниже смотрите результаты Добавлено -- Раньше было у меня - запускаю 5 копий программ с паузой 1 секунда, она так же посылала в интернет и давала результат но гораздо быстрее, чем сейчас - почему? Добавлено сейчас проходит примерно 5 секунд прежде чем я получу результат от Google, хотя в таблице видно что ответы я получаю при наличии слов каждые две секунды. не пойму где теряются 3 секунды |
Сообщ.
#11
,
|
|
|
Emmys
Покопайся в ACS_Classes.pas - похоже там "все схвачено", в частности и кольцевой TAuFIFOStream есть. Остается только размер буфера рассчитать и задать под заданные интервалы чтения |
Сообщ.
#12
,
|
|
|
кто расскажет больше про TAuFIFOStream ?
|
Сообщ.
#13
,
|
|
|
убрал баги и получился закольцованный буфер. ура товарищи
всем спасибо |