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


Автор: Aeore 14.5.2010, 10:58
Пишу библиотеку DLL для звуковой связи по tcp/ip сети. Для передачи звука принял решение использовать поток, на ThreadID которого будут приходить сообщения с данными от ОС. Проблема в следующем: у меня происходит запуск потока в Suspended (т.е. остановленном режиме), потом вызов waveInOpen, затем идет подготовка буферов и, собственно, запуск потока. В потоке в цикле стоит GetMessage(), который принимает сообщение и работает с ним дальше. Проблема в том, что после запуска потока сообщение не принимается (GetMessage() уходит в вечное ожидание), но если поток сразу делать запущеным, то сообщения приходят. Отсюда вопрос -- возможен ли прием (в очередь) сообщений suspended-потоком и если нет, то как такого добиться? И правильно ли я понял источник проблемы ? Я понимаю, что открытие аудио-устройства можно делать прямо в потоке, но пока хотелось бы написать именно так как я описал выше.

функция инициализации (вызывается один раз при запуске программы)
Код

function SAS_InitTransmitter(DeviceID: Integer): Integer;
var
  WaveFormat: TWaveFormatEx;
  I: Integer;
begin
  ...
  AudioOutputDevice := DeviceID;

  TransmitterThread := TAudioTransmitter.Create; // Создаем поток

  with WaveFormat do begin
    wFormatTag := WAVE_FORMAT_PCM;
    nChannels := 1;
    wBitsPerSample := 16;
    nBlockAlign := nChannels * wBitsPerSample div 8;
    nSamplesPerSec := 8000;
    nAvgBytesPerSec := nSamplesPerSec * nBlockAlign;
    cbSize := 0;
  end;

  InDevHandle := 0;
  Result := ifx(waveInOpen(@InDevHandle, AudioOutputDevice, @WaveFormat, TransmitterThread.ThreadID, 0, CALLBACK_THREAD) = MMSYSERR_NOERROR, SAS_E_FAIL, SAS_E_SUCCESS);
  if Result = SAS_E_FAIL then Exit;

  // Готовим CWAVEBUFFERSCOUNT буферов передатчика, размером с фрейм кодирования (20 мс)
  for I := 0 to High(TXBuffers) do begin
    SetLength(inBuffs[I], encframe);
    with TXBuffers[I] do begin
      lpData := @inBuffs[I, 0];
      dwBufferLength := Length(inBuffs[I]) * SizeOf(inBuffs[I, 0]);
      dwBytesRecorded := 0;
      dwUser := I;  // Порядковый номер буфера
      dwLoops := 0;
      Result := ifx(waveInPrepareHeader(InDevHandle, @TXBuffers[I], SizeOf(TWAVEHDR)) = MMSYSERR_NOERROR, SAS_E_FAIL, SAS_E_SUCCESS);
      if Result = SAS_E_FAIL then Exit;
    end;
  end;

  if Result = SAS_E_SUCCESS then begin
    TransmitterThread.Resume; // Запускаем поток!!
    TXInit := True;
  end else
    TransmitterThread.Free;
end;



поток:

Код

constructor TAudioTransmitter.Create;
begin
  inherited Create(True); // Если False, то сообщение принимается
  Priority := tpNormal;
  FreeOnTerminate := False;
  GetMem(payload, 8000);
  PeekMessage(Msg, 0, 0, 0, PM_REMOVE);
end;

destructor TAudioTransmitter.Destroy;
begin
  PostThreadMessage(ThreadID, WM_QUIT, 0, 0);
  FreeMem(payload);
  inherited;
end;

procedure TAudioTransmitter.Execute;
var
  I, enc_size, BuffNo, total_pl, frames: Integer;
  AudioData: TSAS_MSG_AUDIODATA;
begin
  ..
  while not Terminated do begin
    ..

    if GetMessage(Msg, 0, 0, 0) then begin
      case Msg.message of
        MM_WIM_OPEN:
          begin
            ...
          end;

        MM_WIM_DATA:
          begin
            ...

            waveInAddBuffer(InDevHandle, PWAVEHDR(Msg.lParam), SizeOf(TWAVEHDR));
          end;
      end;
    end;

  end;
end;

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