Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Мультимедиа в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 03.02.2010, 12:42   #1
luckydevil
Пользователь
 
Регистрация: 11.12.2009
Сообщений: 10
По умолчанию Как быстро получать данные со звуковой карты.

Добрый день.
Уже долгое время меня волнует следующая проблема.
Я получаю сигнал с аудиокарты, а потом считаю амплитуду каждой гармоники в Дб.
Мне нужно получить сигнал с аудиокарты, с разрешеним по частоте 1 гц. Это значит что буфер в который я хочу загнать данные должен быть не меньше чем сэмпл рейт, а значит что бы получить такой буфер требуется как минимум одна секунда. Однако если сравнить с другими программами, я использую SpectraLab, то данные там берутся значительно быстрее, в десятки раз.
Я пытался поступить следующим образом: брать небольшой буфер, скажем, в 4 раза меньше сэмпл рейта. Тогда у меня разрешение всего 4 герца, но если подшить эти буферы друг к другу, то просто теряем первые 4 герца в спектре, а дальше получаем нужное нам разрешение. Можно например не копировать его, а постоянно получать со звуковой карточки эти маленькие буфера и подшивать их к большому, так правильнее. Но вопрос в том как правильно подшить, ведь фаза в которой приходит синус отлична от той что на конце синуса, и получается искусственное смещение этого синуса. Тогда я двигаю конец этого синуса относительно начала, на каждом сдвиге считаю коэффициент корреляции и сшиваю в той точке где он максимален. Так получается значительно точнее, но когда гармоник много, то понятное дело, результат спектральной плотности мощности получается хуже, ведь нет полной корреляции. Можно каждый синус обработать оконной функцией Хемминга например, тогда разрывы на осциллограмме убьем, но смешение останется, а это главное. Пробовал запускать несколько потоков с большим буфером, но ускорения не достиг (не знаю почему).
Если есть у кого то какие либо мысли, как брать буфер размером с сэмпл рейт за время меньше секунды, или как преодолеть эту проблему пожалуйста поделитесь, ведь эта проблема как то решена в SpecraLabе. С со звуковухой работаю на WinApi, без DirectSound, это Windows Multimedia (waveInOpen, waveInStart и др. )
Объяснение наверное смутное, могу нарисовать картинки если потребуется. Буду очень признателен за помощь.
luckydevil вне форума Ответить с цитированием
Старый 03.02.2010, 13:10   #2
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,713
По умолчанию

ваш вопрос ясен... решение с накоплением не годится ввиду несинхронности отсчетов, спектр будет "бредом"... да, конечно, если вы учитываете корреляцию это уменьшает погрешность, но полностью вы ее все равно не учтете, так что это тоже отпадает...

...у меня при 2048 точечном БПФ и размере буфера 3000 (мне не нужны разрешения в 1Гц) и Fd=44100, 8бит,1 канал времени уходит порядка сотни миллисекунд, тоже api... время обработки определяется быстродействием самой машины (у меня 900МГц, 128 ОЗУ).
...думается SpectraLab лишь отображает быстро, для пользователя... одним потоком грузит, а при просмотре то чего накопил, отображает.
...если не секрет, зачем вам такие огромные разрешения в 1Гц?
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation

Последний раз редактировалось raxp; 03.02.2010 в 13:14.
raxp вне форума Ответить с цитированием
Старый 03.02.2010, 13:23   #3
luckydevil
Пользователь
 
Регистрация: 11.12.2009
Сообщений: 10
По умолчанию

Цитата:
Сообщение от raxp Посмотреть сообщение

...у меня при 2048 точечном БПФ и размере буфера 3000 (мне не нужны разрешения в 1Гц) и Fd=44100, 8бит,1 канал времени уходит порядка сотни миллисекунд, тоже api... время обработки определяется быстродействием самой машины (у меня 900МГц, 128 ОЗУ).
...если не секрет, зачем вам такие огромные разрешения в 1Гц?
Если генерить 44100 семплов в секунду, то буфер 3000 заполнится за 70 миллисекунд. Поэтому и порядка сотни миллисекунд идет заполнение. А у меня буфер размером никак не меньше сэмпл рейта, а если и для фурье нужно взять меньше меньше, то берем все равно большой буффер и делаем прореживание. Такое уж требование сделать так и никак не хуже 1 герца. У меня не расчеты тормозят, а получение буфера из карточки.
luckydevil вне форума Ответить с цитированием
Старый 03.02.2010, 14:19   #4
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,713
По умолчанию

вы с такой точностью говорите за сколько он заполнится и совершенно игнорируете быстродействие машины, ее загруженность... win это не система реального времени...

...теперь к делу, только-что gettickcount-ом промерил у себя: получение буфера в 10100 значений занимает 40-50мс (прыгает), причем это время затрачиваемое для добавления, заметьте, в tchart (сделал для визуализации) ...больше выставить не могу, т.к. машина не позволяет. Без использования компонента, на порядки быстрее, т.к. используется указатель на область данных в памяти.

В связи с чем проверьте у себя:
1- нет-ли у вас каких-нить процедур, тормозящих процесс?
Код:
procedure waveInProc2(hwi: HWAVEIN; uMsg,dwInstance,dwParam1,dwParam2: DWORD);stdcall;
var i      : integer;
    data16 : PData16;
    temp   : pWaveHdr;
    //
    a,f,cntval: double;
begin
 if (uMsg=WIM_DATA)and(stp) then begin
  //form1.series1.clear;
  z1:= gettickcount;

  temp:= adr2;
  if adr2= @bufhead1 then adr2:= @bufhead2
   else adr2:= @bufhead1;

  WaveInAddBuffer(hwi,adr2,SizeOf(TWaveHdr));
  data16:= PData16(temp.lpData);

  //for i := 0 to BufSize - 1 do
   //form1.series1.add(data16^[i]);

 z2:= gettickcount - z1
 end
end;
2- используете-ли вы буферизацию (два буфера) данных для накопления и вывода (как у меня)?
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation
raxp вне форума Ответить с цитированием
Старый 03.02.2010, 14:56   #5
luckydevil
Пользователь
 
Регистрация: 11.12.2009
Сообщений: 10
По умолчанию

вот если поставить в этом примере сэмпл рейт 11025 то чарт будет обновляться раз в секунду. Так же если сделать буфер 44100 и оставить сэмпл рейт таким же - 44100, то процедура waveInProc2 будет вызываться раз в секунду. Потому что пока не заполнен буфер сообщение WIM_DATA не будет послано. А вы здесь просто готовый массив забираете, и буфер новый для записи даете. Это быстро. У меня вопрос в том что как сделать, чтобы аудиокарта быстрее записывала данные в буфер, который ей предложили, а если этого не возможно, то каким образом получить разрешение в 1 герц из маленького буффера.
luckydevil вне форума Ответить с цитированием
Старый 03.02.2010, 15:47   #6
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,713
По умолчанию

вот теперь проясняется, почему у вас это так долго... вы не слушаете, в буфер аудиокарта записывает быстро, это вы отображаете его медленно.

...пора-бы вам код свой выложить, а то беспредметный разговор получается.

upd
-------

фурье-анализ нельзя применять для анализа длительностей, а именно так вы и поступаете, спектр будет неадекватным.
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation

Последний раз редактировалось raxp; 03.02.2010 в 16:40.
raxp вне форума Ответить с цитированием
Старый 03.02.2010, 16:21   #7
luckydevil
Пользователь
 
Регистрация: 11.12.2009
Сообщений: 10
По умолчанию

а я говорю медленно :-). если я маленький буфер возьму и разкопирую его и потом склею то получится тот же большой буфер. И фурье и вся остальная работа только с ним. А времени на все про все уйдет в несколько раз меньше. Взял маленький буфер 1/4 от семпл рейта, разкопировал его и залил в большой. Теперь работам с большим а времени уходит в 4 раза меньше. Я измерял на все вычисления уходят десятки миллисекунд
Я пока поменял склеивание с помощью корреляции на более простой, но эффективный способ. Берем один кусок синусоиды с начала и другой с конца что бы туда заведомо помещался 1 период главной гармоники. Так как частоту менее 20 герц мне можно не мерить это сделать можно. Теперь находим в первом и во втором отрезке минимумы и синус берем от первого минимума до другого. Они получатся в почти одинаковых фазах и ошибку минимальна. Конечно дурацкий способ, но пока лучше ничего нету.
luckydevil вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Выбор звуковой карты... Kvinto Мультимедиа в Delphi 9 20.10.2009 15:03
OpenSuSe настройка звуковой карты? mv28jam Операционные системы общие вопросы 1 06.10.2009 13:34
Генератор случайных чисел на основе шума звуковой карты dx+ Общие вопросы Delphi 7 20.06.2009 09:52
Как получать данные из чертежа CAD системы Компас V7? Stilet Общие вопросы Delphi 0 28.01.2009 16:11
Есть ли возможность управлять драйвером спец. звуковой карты через длл или как то иначе? chysti Win Api 2 14.02.2008 12:57