Потоковая запись звука

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Потоковая запись звука

Сообщение Nikolas » 23.04.2015 18:21:44

Здравствуйте!
Мне потребовалось организовать потовую (непрерывную?) запись (и последующее воспроизведение) звука с использованием OpenAL.
Если по воспроизведением есть справочные материалы как это сделать, то как организовать запись я понять не могу.
Может кто-нибудь подсказать как это сделать?

Добавлено спустя 53 минуты 52 секунды:
Попробовал сделать такой тестовый примерчик на основе исходника из состава FPC.

константы, типы, переменные

Код: Выделить всё
const
  Seconds = 1;                            //- длительность записи 1 сек
  Frequency = 8000;                       //- частота дискретизации 8 КГц
  Format = AL_FORMAT_MONO8;              //- формат записи 16-бит моно
  SampleSize = 1;                        //- размер сэмпла AL_FORMAT_MONO8 в байтах
  BufferSize = Frequency*SampleSize*Seconds; //- размер буфера (частота * 2bytes(16-bit)) * время

type
  TCaptureBuffer = array[0..BufferSize-1] of ALubyte; //- внешний буфер для записи из openAL
  PCaptureBuffer = ^TCaptureBuffer;         

  Str: String;
  Flag: Boolean = True;
  Buffers: TList;
  CaptureBufferPoint: pCaptureBuffer;

  pCaptureDevice: pALCDevice;                  //- устройство записи аудио
  CaptureBuffer: TCaptureBuffer; //- внешний буфер для записи из openAL, размер которого вычислен для записи 1 сек                       
  Samples: ALInt;                //- количество  звуковых сэмплов


процедура записи

Код: Выделить всё
//- Setup the input capture device (default device)
  Str:='Setting up alcCaptureOpenDevice to use default device'; Memo1.Lines.Add(Str);
  pcaptureDevice:=alcCaptureOpenDevice(nil, Frequency, Format, BufferSize);
  if pcaptureDevice=nil then begin
    raise exception.create('Capture device is nil!');
    exit;
  end;

  //- Start capturing data
  alcCaptureStart(PCaptureDevice);

  Flag:=true;
  While Flag do begin
    //- Сapturing data samples
    repeat
      alcGetIntegerv(pCaptureDevice, ALC_CAPTURE_SAMPLES, ALsizei(sizeof(ALint)), @samples);
      Str:=IntToStr(samples)+'/'+IntToStr(Seconds*Frequency)+' samples'; form1.Caption:=Str;
    until samples>=seconds*frequency;

    //- Capture the samples into our capture buffer
    alcCaptureSamples(pCaptureDevice, @CaptureBuffer, samples);

    if Buffers.Count>=9 then begin
      Buffers.Delete(0);
    end;
    New(CaptureBufferPoint);
    CaptureBufferPoint^:=CaptureBuffer;
    Buffers.Add(CaptureBufferPoint);

    Application.ProcessMessages;
  end;                               

    //- Capture the samples into our capture buffer
    alcCaptureSamples(pCaptureDevice, @CaptureBuffer, samples);
    form1.Caption:=IntToStr(Samples);
    application.ProcessMessages;
  end;

  //- Done recording
  alcCaptureStop(pCaptureDevice);

  //- Shutdown/Clean up the capture stuff
  alcCaptureCloseDevice( pCaptureDevice );                 


С одной стороны все работает.
Но непонятно из-за чего программа "жрет" память блоками по 8К.
С чем такое может быть связано? Есть ли другие способы реализации?
Nikolas
новенький
 
Сообщения: 14
Зарегистрирован: 26.08.2014 13:41:37

Re: Потоковая запись звука

Сообщение wavebvg » 24.04.2015 11:34:24

Код: Выделить всё
New(CaptureBufferPoint);
CaptureBufferPoint^:=CaptureBuffer;
Buffers.Add(CaptureBufferPoint);

Что Вы этим пытаетесь добиться?
wavebvg
постоялец
 
Сообщения: 355
Зарегистрирован: 28.02.2008 04:57:35

Re: Потоковая запись звука

Сообщение Nikolas » 24.04.2015 14:15:16

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

Добавлено спустя 5 минут 13 секунд:
upd: причиной утечки памяти было некорректное освобождение ресурсов в TList, переделал на такой вариант

Код: Выделить всё
if Buffers.Count>=9 then begin
  CaptureBufferPoint:=Buffers.Extract(Buffers.First);
  Dispose(CaptureBufferPoint);
  CaptureBufferPoint:=nil;
end;   
Nikolas
новенький
 
Сообщения: 14
Зарегистрирован: 26.08.2014 13:41:37

Re: Потоковая запись звука

Сообщение wavebvg » 24.04.2015 18:50:31

В лоб:
Код: Выделить всё
Buffers.Add(Pointer(CaptureBuffer));

...
Код: Выделить всё
if Buffers.Count>=9 then
begin
  Buffers.Extract(Buffers.First);
end;

...
Для извлечения кастуем так, чтобы не потерять значимую часть (потому что SizeOf(Pointer) может быть как 4 так и 8)

Имелось в виду: зачем так сложно, напрямую с памятью, да ещё без опыта...
Лучше бы воспользовались бы Buffers: TMemoryStream и не забивали голову ручным управлением.
wavebvg
постоялец
 
Сообщения: 355
Зарегистрирован: 28.02.2008 04:57:35


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 254

Рейтинг@Mail.ru