Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Звук, графика и видео > Как с LinIn получить 24bit звук???


Автор: ivan219 6.1.2009, 04:16
Получить 8 или 16bit можно а вот 24bit никак smile 

Пример в архиве.

Автор: Alexeis 6.1.2009, 12:52
ivan219, а твоя звуковая карта на это способна? Разрядность определяется возможностями АЦП, если у тебя 16 битный АЦП, то как из него выжать 24 бита?

Автор: ivan219 6.1.2009, 14:53
Поддержевает!!!

Автор: Alexeis 6.1.2009, 15:46
ivan219, но ты ведь сам установил 16 бит звук

см код

Добавлено через 4 секунды
Код

begin
 Result := False;
 WaveFormat.wFormatTag := WAVE_FORMAT_PCM;
 WaveFormat.nChannels := 2;
 WaveFormat.nSamplesPerSec := 96000;
 WaveFormat.wBitsPerSample := 16;

Автор: Alexeis 6.1.2009, 16:18
Еще вот посмотрел форматы поддерживаемые интерфейсом waveInХХХХ. Вот полный перечень

Цитата

WAVE_FORMAT_1M08  11.025 kHz, mono, 8-bit
WAVE_FORMAT_1M16  11.025 kHz, mono, 16-bit
WAVE_FORMAT_1S08  11.025 kHz, stereo, 8-bit
WAVE_FORMAT_1S16  11.025 kHz, stereo, 16-bit
WAVE_FORMAT_2M08  22.05 kHz, mono, 8-bit
WAVE_FORMAT_2M16  22.05 kHz, mono, 16-bit
WAVE_FORMAT_2S08  22.05 kHz, stereo, 8-bit
WAVE_FORMAT_2S16  22.05 kHz, stereo, 16-bit
WAVE_FORMAT_4M08  44.1 kHz, mono, 8-bit
WAVE_FORMAT_4M16  44.1 kHz, mono, 16-bit
WAVE_FORMAT_4S08  44.1 kHz, stereo, 8-bit
WAVE_FORMAT_4S16  44.1 kHz, stereo, 16-bit
WAVE_FORMAT_96M08  96 kHz, mono, 8-bit
WAVE_FORMAT_96S08  96 kHz, stereo, 8-bit
WAVE_FORMAT_96M16  96 kHz, mono, 16-bit
WAVE_FORMAT_96S16  96 kHz, stereo, 16-bit
 

Среди них нет формата 24 бит. Вероятно нужно использовать более новый API.

Автор: ivan219 6.1.2009, 18:21
А как где барть может исходничёк есть smile 

Автор: Alexeis 6.1.2009, 19:09
  Гм... сейчас покопал ни OpenAl ни DirectSound не умеют определять наличие поддержки формата 24 бита. Помниться в фубаре тоже такая проблема. Фубар не знает какую разрядность поддерживает звуковая карта, но предлагает установить насильно формат 24 бита если юзер уверен в поддержке. 

Так что попробуй вместо 

Код

WaveFormat.wBitsPerSample := 16;


Написать
Код

WaveFormat.wBitsPerSample := 24;


Может и сработает.

IDirectSoundCapture очень мало инфы. На русском так вообще не нашел. Нужно искать.
Если с WaveIn не прокатит то с IDirectSoundCapture должно прокатить, но опять же ставить нужно не проверяя.

Автор: ivan219 7.1.2009, 00:21
Цитата(Alexeis @  6.1.2009,  19:09 Найти цитируемый пост)
WaveFormat.wBitsPerSample := 24;

это дело пробовал но ведь там есть буфер
Код

 TWavArrayBuf = array[0..4095] of Smallint;// 16bit
 PWavArrayBuf = ^TWavArrayBuf;

Как с ним быть ведь 3-х байтного типа нет smile а Integer непомогает идёт искажение smile 

Автор: Alexeis 7.1.2009, 01:29
Тякс DirectSoundCapture удалось получить нестандартные PCM форматы, но тема по сути не меняется.
Буфер будет из блоков по 6 байт или по 3 байта. Выборки можно доставать при помощи битовых операций. 
  Например если полезные байты 3 младших делаешь операцию AND с маской $00FFFFFF, если в 3х старших то с маской $FFFFFF00 + сдвиг вправо на 8 разрядов.

Автор: Alexeis 7.1.2009, 02:20
Значит дело оказалось еще хирее. Числа ведь представлены в 3х байтовом дополнительном коде.
Значит для стерео блока я использую следующую структуру 
Код

  TSmplGroup6 = packed Record
    dw : Cardinal;
    w  : Word;
  end;


Массив определяю так
Код

  TSndDataType6 = array[0..High(Integer) div 6 - 1] of TSmplGroup6;
  PSndDataType6 = ^TSndDataType6;


Значит положительные числа достаются правильно вот так 
Код

      LeftCh := data6[i].dw and $00FFFFFF; //достаем первые 3 байта первого сэмпла
      RightCh:= (data6[i].dw and $FF000000) shr 24; //достаем 1й байт второго сэмпла
      RightCh:= RightCh OR (Cardinal(data6[i].w) shl 8); //достаем 2й и 3й байты 2го сэмпла


Однако если число отрицательное то у него знаковый бит 24й а не 32й как у Integer, по этому отрицательные числа нужно подправлять добавив $FF в старший разряд. 
Ну и в итоге для вывода выборок в чарт применяю такой код

Код

  datasize := datasize div 6;
  for I := 0 to datasize - 1
  do
    Begin
      LeftCh := data6[i].dw and $00FFFFFF;
      RightCh:= (data6[i].dw and $FF000000) shr 24;
      RightCh:= RightCh OR (Cardinal(data6[i].w) shl 8);
      if RightCh >= $800000
      then
        RightCh := RightCh OR $FF000000;

      if LeftCh >= $800000
      then
        LeftCh := LeftCh OR $FF000000;

      Series1.AddXY(i, LeftCh);
      Series2.AddXY(i, RightCh);
    End;


Кстати запись веду через DirectSound. Если интересно приведу весь код.

Автор: ivan219 7.1.2009, 14:23
Цитата(Alexeis @  7.1.2009,  02:20 Найти цитируемый пост)
Кстати запись веду через DirectSound. Если интересно приведу весь код.

Да если можно smile 

Автор: Alexeis 7.1.2009, 21:22
  Код пробный, но работает.

Автор: ivan219 12.9.2009, 18:43
Я всётаки его добил бинарная математика рулитsmile

Только мне не даёт покоя два вареанта решения этой проблемы.

Для моно 24бит

Код

nChannels := 1;
wBitsPerSample := 24;


вареант1
Код

type
  PByte = ^TByte;
  TByte = Array[0..0] of Byte;

var
  SignalL: Array of Longint;
  A, B, C: Byte;

         A := PByte(PWaveHdr(Param1).lpData)^[I * 3];
         B := PByte(PWaveHdr(Param1).lpData)^[I * 3 + 1];
         C := PByte(PWaveHdr(Param1).lpData)^[I * 3 + 2];
         if C and (1 shl 7) <> 0 then SignalL[I] := ($FF shl 24) or (C shl 16) or (B shl 8) or A
         else SignalL[I] := (C shl 16) or (B shl 8) or A;


Вареант 2
Код

type
  PByte = ^TByte;
  TByte = Array[0..0] of Byte;

var
  SignalL: Array of Longint;
  A, B, C: Byte;

         A := PByte(PWaveHdr(Param1).lpData)^[I * 3];
         B := PByte(PWaveHdr(Param1).lpData)^[I * 3 + 1];
         C := PByte(PWaveHdr(Param1).lpData)^[I * 3 + 2];

         SignalL[I] := ((C shl 24) or (B shl 16) or (A shl 8) or 0);
         SignalL[I] := SignalL[I] div 256;


Оба вроде работают хорошо но какой выбрать???

Автор: Alexeis 15.9.2009, 09:34
  Желательно без деления. Но есть еще более быстрый вариант.
Код

var
  intgr : Integer;
begin
....//цикл
  intgr := 0;
  Move(PByte(PWaveHdr(Param1).lpData)^[n], intgr, 3);
  if intgr >= $800000 then SignalL[I] := intgr or $FF000000 else SignalL[I] := intgr;
  inc(n, 3);
...

Автор: ivan219 21.10.2009, 21:39
 smile 

Автор: Alexeis 22.10.2009, 19:32
ivan219, что это значит? Появляешься через 1.5 месяца чтобы отпостить смайлик? Чего там? Заработало или нет?

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