Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2008.03.02;
Скачать: CL | DM;

Вниз

waveOut и waveIn одновременно   Найти похожие ветки 

 
Sirus   (2007-02-08 09:58) [0]

Привет Мастерам...
Есть проблемка:
Подскажите как организовать сабж?
то есть нужно звук идущий из микрофона сразу же воспроизводить. (Сохранение записи в WAV и его воспроизведение не интересует)


 
medved_68 ©   (2007-02-08 10:08) [1]


> то есть нужно звук идущий из микрофона сразу же воспроизводить.
>  

Sirus Заполненый буфер (который тебе вернет драйвер зв.карты) сразу ставь в очередь на воспроизведение, а взамен него создавай новый или бери тот который вернется из очереди воспроизведения и ставь в очередь на запись. В принципе по сабжу: Есть исходник проги - пишет с микрофона в поток - по нажатию воспроизводит. Если подкорректировать то проблема снимется. :))))


 
Сергей М. ©   (2007-02-08 10:10) [2]


> нужно звук идущий из микрофона сразу же воспроизводить


Если аудиоподсистема не поддерживает fullduplex-режим, то не получится.


 
Sirus   (2007-02-08 10:23) [3]

Читал в доках что одновременно открыть устройства на запись и воспроизведение не получится.
Я попытался сделать так:
Открываю запись
получаю буфер записи
закрываю запись и открываю вопроизведение
отправляю полученный буфер на воспроизведение
закрываю воспроизведение
И ни черта не получается :( ничего не слышно

> Есть исходник проги - пишет с микрофона в поток - по нажатию воспроизводит. Если подкорректировать то проблема снимется. :))))

Был бы очень признателен за исходник

И как узнать поддерживается ли на компе полный дуплекс?


 
medved_68 ©   (2007-02-08 10:49) [4]


> И как узнать поддерживается ли на компе полный дуплекс?

Открыть устройство на запись проанализировать открытие на предмет ошибки, сделать попытку открыть устройство на воспроизведение если функция вернет ИД устройства - сделвть вывод о поддержке, если нет (ошибка открытия устройства) .....на нет и суда нет :)))


 
medved_68 ©   (2007-02-08 10:50) [5]


> отправляю полученный буфер на воспроизведение

А как отправляешь???


 
TRUNK ©   (2007-02-08 10:57) [6]


> Sirus   (08.02.07 09:58)  

Если "нужно звук идущий из микрофона сразу же воспроизводить", то связываться с waveOut и waveIn имеет смысл, только если нужно производить обработку звука в реальном времени ("почти реальном" - задержка будет в любом случае).

Тут нужно ещё решить сложную проблему синхронизации. Наилучший вариант, когда и запись, и воспроизведение синхронизируются одним и тем же источником, т.е. используется одна звуковая карта и на вход, и на выход. Делал я как-то программу, которая в "почти реальном" времени меняет АЧХ - больше половины времени потратил на подгонку синхронизации.


 
Плохиш ©   (2007-02-08 11:18) [7]


> Sirus   (08.02.07 09:58)  
> то есть нужно звук идущий из микрофона сразу же воспроизводить.

Хм, я конечно понимаю, что сайт по делфи и всё такое, но у меня и без сторонних программ всё так и работает. Может стоит, для начала, "Регулятор громкости" запустить и посмотреть, чем же там порегулировать можно?


 
Sirus   (2007-02-08 11:55) [8]


>> отправляю полученный буфер на воспроизведение
> А как отправляешь???

   
MM_WIM_DATA: begin
     Hdr:=PWaveHdr(msg.LParam);
     WaveInStop(WaveIn^);
     if WaveIn<>nil then WaveInReset(WaveIn^);
     if WaveIn<>nil then WaveInClose(WaveIn^);
     Dispose(WaveIn);
     WaveOut:=new(PHWaveOut);
     WaveOutOpen(WaveOut,0,@WaveFormat,handle,0,CALLBACK_WINDOW);
     WaveOutPrepareHeader(WaveOut^,Hdr,sizeOf(TWaveHdr));
     WaveOutWrite(WaveOut^,Hdr,Sizeof(TWaveHdr));
end;



> Хм, я конечно понимаю, что сайт по делфи и всё такое, но у меня и без  
> сторонних программ всё так и работает. Может стоит, для начала,
> "Регулятор громкости" запустить и посмотреть, чем же там порегулировать
> можно?

Меня такой вариант не устраивает, не хочу бегать по пользователям и каждому включать микрофон в параметрах громкости Windows


 
Sirus   (2007-02-08 12:02) [9]

Вот весь код. Он не работает.
Подскажите что неправильно и как его исправить.

unit main;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, MMSystem, ShellAPI;

type
 TArrayBuf = array[0..1023]of byte;
 PArrayBuf = ^TArrayBuf;

 TForm1 = class(TForm)
   Button1: TButton;
   Button2: TButton;
   Label1: TLabel;
   Label2: TLabel;
   procedure Button2Click(Sender: TObject);
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
   WaveFormat:TWaveFormatEx;
   WaveIn:PHWaveIn;
   WaveOut:PHWaveOut;
   IsOn:boolean;
   procedure WNDPROC(var msg:TMessage); override;
   procedure InitWave(r: boolean);
 end;

var
 Form1: TForm1;
 ci, co: integer;

implementation

{$R *.dfm}

Procedure TForm1.WNDPROC(var msg:TMessage);
 var Hdr: PWaveHdr;
     WaveBuf: PArrayBuf;
     i: integeR;
begin
 INHERITED;
 case msg.Msg of
   MM_WIM_OPEN: begin
     //Открытие записи
   end;
   MM_WIM_CLOSE: begin
     //Закрытие записи
   end;
   MM_WIM_DATA: begin
     ci:=ci+1;
     label1.Caption:=IntTostr(ci);
     Hdr:=PWaveHdr(msg.LParam);
     WaveInStop(WaveIn^);
     if WaveIn<>nil then WaveInReset(WaveIn^);
     if WaveIn<>nil then WaveInClose(WaveIn^);
     Dispose(WaveIn);
     WaveOut:=new(PHWaveOut);
     WaveOutOpen(WaveOut,0,@WaveFormat,handle,0,CALLBACK_WINDOW);
     WaveOutPrepareHeader(WaveOut^,Hdr,sizeOf(TWaveHdr));
     WaveOutWrite(WaveOut^,Hdr,Sizeof(TWaveHdr));
   end;
   MM_WOM_DONE: begin
     co:=co+1;
     label2.Caption:=IntTostr(co);
     WaveOutClose(WaveOut^);
     Dispose(WaveOut);
     if IsOn=False Then Exit;
     WaveIn:=new(PHWaveIn);
     WaveInOpen(WaveIn,0,@WaveFormat,handle,0,CALLBACK_WINDOW);
     WaveBuf:=new(PArrayBuf);
     Hdr:=new(PWaveHdr);
     with Hdr^ do begin
       lpData:=pointer(WaveBuf);
       dwBufferLength:=sizeof(WaveBuf);
       dwBytesRecorded:=0;
       dwUser:=0;
       dwFlags:=0;
       dwLoops:=0;
     end;
     WaveInPrepareHeader(WaveIn^,Hdr,sizeOf(TWaveHdr));
     WaveInAddBuffer(WaveIn^,Hdr,Sizeof(TWaveHdr));
     WaveInStart(WaveIn^);
   end;
 end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Initwave(True);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
Initwave(False);
end;

procedure TForm1.InitWave(r: boolean);
 var WaveHdr: PWaveHdr;
     WaveBuf: PArrayBuf;
     i: integer;
begin
 ci:=0;
 co:=0;
 if r then begin
   IsOn:=True;
   WaveFormat.wFormatTag:=WAVE_FORMAT_PCM;
   WaveFormat.nChannels:=1;
   WaveFormat.nSamplesPerSec:=44100;
   WaveFormat.nAvgBytesPerSec:=44100;
   WaveFormat.nBlockAlign:=4;
   WaveFormat.wBitsPerSample:=8;
   WaveIn:=new(PHWaveIn);
   WaveInOpen(WaveIn,0,@WaveFormat,handle,0,CALLBACK_WINDOW);
   WaveBuf:=new(PArrayBuf);
   WaveHdr:=new(PWaveHdr);
   with WaveHdr^ do begin
     lpData:=pointer(WaveBuf);
     dwBufferLength:=sizeof(WaveBuf);
     dwBytesRecorded:=0;
     dwUser:=0;
     dwFlags:=0;
     dwLoops:=0;
   end;
   WaveInPrepareHeader(WaveIn^,WaveHdr,sizeOf(TWaveHdr));
   WaveInAddBuffer(WaveIn^,WaveHdr,Sizeof(TWaveHdr));
   WaveInStart(WaveIn^);
 end else begin
   IsOn:=False;
   WaveInStop(WaveIn^);
   if WaveIn<>nil then WaveInReset(WaveIn^);
   if WaveIn<>nil then WaveInClose(WaveIn^);
   Dispose(WaveIn);
 end;
end;

end.


 
TRUNK ©   (2007-02-08 12:40) [10]

Для описанных целей способ работы через сообщения не годится,
особенно учитывая размер буфера.

P.S. А с какой радости WaveFormat.nBlockAlign = 4, если он равен 1?
P.P.S. nBlockAlign := nChannels*(wBitsPerSample div 8)


 
Sirus   (2007-02-08 12:48) [11]

> Для описанных целей способ работы через сообщения не годится,
> особенно учитывая размер буфера.

подскажи способ который сгодится.

> P.P.S. nBlockAlign := nChannels*(wBitsPerSample div 8)
Спасибо


 
TRUNK ©   (2007-02-08 13:05) [12]

Для того чтобы быстро узнать о завершении обработки буфера, нужно использовать так называемый polling, т.е. постоянный опрос состояния флага WHDR_DONE в TWaveHdr.dwFlags. Для этого я делал отдельный поток, который и занимался всем процессом по записи и/или воспроизведению звука.


 
Плохиш ©   (2007-02-08 13:41) [13]


> Меня такой вариант не устраивает, не хочу бегать по пользователям
> и каждому включать микрофон в параметрах громкости Windows

http://narod.yandex.ru/cgi-bin/yandmarkup?cluster=14&prog=0x2757571A&HndlQuery=418343216&PageNum=0&g=3&d=0&q0=4 22254800&p=


 
medved_68 ©   (2007-02-08 13:41) [14]


> MM_WIM_DATA: begin
>      Hdr:=PWaveHdr(msg.LParam);
>      WaveInStop(WaveIn^);
>      if WaveIn<>nil then WaveInReset(WaveIn^);
>      if WaveIn<>nil then WaveInClose(WaveIn^);
     Dispose(WaveIn);
      WaveOut:=new(PHWaveOut);
>      WaveOutOpen(WaveOut,0,@WaveFormat,handle,0,CALLBACK_WINDOW);
>
>      WaveOutPrepareHeader(WaveOut^,Hdr,sizeOf(TWaveHdr));
>
>      WaveOutWrite(WaveOut^,Hdr,Sizeof(TWaveHdr));
> end;

Sirus   ну и что же ты хотел услышать???? Ведь ты собственноручно убиваешь буфер с звуковыми данными и создаешь новый который ставишь в очередь на воспроизведение мда уж.....комментарии излишни :)))


 
Sirus   (2007-02-09 05:45) [15]

Я думал буфер остается в переменной Hdr


 
Vovan # 2   (2007-02-09 08:54) [16]

Никаких выделений памяти при MM_WIM_DATA, только сразу другой подставить буфер.


 
medved_68 ©   (2007-02-09 13:39) [17]


> Я думал буфер остается в переменной Hdr

:))) Остается, но не буфер а указатель на него (Hdr:=PWaveHdr). А после Dispose указатель фактически указывает на недоступную область памяти. Поэтому если хочешь работать так, то сначала выдели новую память, перелей туда звуковые данные, и только потом освобождай то что пришло от драйвера. :))


 
Alter Ego   (2007-03-28 16:57) [18]


> Если "нужно звук идущий из микрофона сразу же воспроизводить",
>  то связываться с waveOut и waveIn имеет смысл, только если
> нужно производить обработку звука в реальном времени ("почти
> реальном" - задержка будет в любом случае).
>

Поподробнее пожалуйста.
Я хочу цеплять DSP эфекты (библиотека BASS_FX) на входящий из микрофона сигнал (типа електрогитарная примочка).


 
Сергей М. ©   (2007-03-28 17:09) [19]


> Alter Ego   (28.03.07 16:57) [18]


> типа електрогитарная примочка


"Типа електрогитарные примочки" при посредстве BASS сойдут разве что для программных экспериментов.

Серьезные же "типа електрогитарные примочки" реализуются при посредстве ASIO, ALSA, к коим BASS не имеет ни малейшего отношения, поскольку попросту не использует эти технологии и интерфейсы.



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

Текущий архив: 2008.03.02;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.018 c
15-1201467030
Иксик
2008-01-27 23:50
2008.03.02
Очень нужен кто-нибудь с американским IP


2-1202561165
oleg_teacher
2008-02-09 15:46
2008.03.02
маска


2-1202472962
Дилан
2008-02-08 15:16
2008.03.02
treeview


15-1201344684
Beastie Boys
2008-01-26 13:51
2008.03.02
Как изменить файл bootfont.bin?


2-1202464753
Artem
2008-02-08 12:59
2008.03.02
Abstract Error в ListBox