отображение данных в реальном времени на осциллографе (qwt)

Я пытаюсь создать программу, используя Qt (c ++), которая может записывать звук с моего микрофона, используя QAudioinput и QIODevice.
Теперь я хочу визуализировать мой сигнал

Любая помощь будет оценена. Спасибо

[Edit1] — скопировано из вашего комментария (Спектре)

  • У меня есть только один буфер для обоих каналов
  • Я использую Qt, значение канала чередуется в буфере
  • это как я разделяю ценности

    for ( int i = 0, j = 0; i < countSamples ; ++j)
    {
    YVectorRight[j]=Samples[i++];
    YVectorLeft[j] =Samples[i++];
    }
    
  • после того, как я построю YvectorRight и YvectorLeft. Я не вижу, как запустить только один канал

1

Решение

Он сделал это несколько лет назад для студентов во время урока. Я надеюсь, что вы знаете, как работают осциллографы, поэтому вот только основы:

  1. временная база

    • fsmpl частота дискретизации входного сигнала [Гц]

    Попробуйте использовать как можно больше (44100,48000, ???) поэтому максимальная обнаруженная частота fsmpl/2 это дает вам вершину оси времени. Нижний предел определяется длиной буфера

  2. рисовать

    Создайте функцию, которая будет визуализировать ваш буфер выборки с указанного начального адреса (внутри буфера) с помощью:

    • Y-шкала … настройка амплитуды
    • Смещение по оси Y … Вертикальное положение луча
    • Смещение по оси X … Сдвиг по времени или горизонтальное положение

    Это можно сделать, изменив начальный адрес или просто сместив кривую по оси X

  3. уровень

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

    • амплитуда: ( < lvl ) -> ( > lvl )
    • амплитуда: ( > lvl ) -> ( < lvl )

    Есть много других возможностей для уровня, таких как глюк, относительный край, …

  4. предварительный просмотр

    Вы можете собрать все это, например, так: у вас есть start address переменная, поэтому выборка данных в некоторый буфер непрерывно и по вызову таймера level с start address (и обновить его). Тогда назовите ничью с новым start address и добавить timebase period в start address (конечно с точки зрения ваших образцов)

  5. многоканальный

    я использую Линия IN, поэтому у меня есть стереовход (A, B = слева, справа), поэтому я могу добавить некоторые другие вещи, такие как:

    • Уровень источника (A,B,никто)
    • режим рендеринга (время, Чебышев (кривая Лиссажу, если он замкнут))
    • Чебышев = x ось A, y ось B это создает знаменитые чебышевские образы, которые хороши для зависимых синусоидальных сигналов. Обычно образуются круги, эллипсы, искаженные петли …
  6. разное

    Вы можете добавить фильтры для каналов, эмулирующих емкость или заземление входа и многое другое

  7. графический интерфейс пользователя

    Вам нужно много настроек, я предпочитаю аналоговые ручки вместо кнопок / полос прокрутки / ползунков, как на реальном осциллографе

    • (полу) аналоговые значения: амплитуда, временная база, уровень, смещение по оси X, смещение по оси Y
    • дискретные значения: режим уровня (/,), источник уровня (A, B, -), каждый канал (прямое включение, заземление, выключение, пропускная способность включена)

Вот несколько скриншотов моего осциллографа:

осциллограф
осциллограф

Вот скриншот моего генератора:

генератор

И, наконец, после добавления некоторых БПФ также Spectrum Analyzer

Анализатор спектра

PS.

  • Я начал с DirectSound но это много отстой из-за глючных / нефункциональных обратных вызовов буфера
  • я использую WinAPI WaveIn / Out для всего звука в моих приложениях сейчас. После нескольких изысков это лучше всего подходит для моих нужд и имеет лучшую задержку (Directsound слишком медленный более чем в 10 раз), но для осциллографа он бесполезен (мне нужна низкая задержка, в основном для эмуляторов)

Btw. У меня есть эти три приложения как связываемые классы подокна C ++ (Borland)

  • и последний раз использовался с моим эмулятором ATMega168 для отладки моего драйвера BLDC без датчиков
  • здесь вы можете попробовать мой Осциллограф, генератор и анализатор спектра Если вы перепутали с загрузкой, прочтите комментарии под этим постом кстати пароль: «осцилл»

Надеюсь, это поможет, если вам нужна помощь, просто прокомментируйте меня

Триггер [Edit1]

Вы запускаете все каналы одновременно, но условие запуска проверяется обычно только с одного. Теперь реализация проста, например, условие триггера быть A (левый) канал поднимается над уровнем так:

  1. Сначала сделайте непрерывное воспроизведение без написанного триггера, вот так:

    for ( int i = 0, j = 0; i < countSamples ; ++j)
    {
    YVectorRight[j]=Samples[i++];
    YVectorLeft[j] =Samples[i++];
    }
    // here draw or FFT,draw  buffers YVectorRight,YVectorLeft
    
  2. Добавить триггер

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

    // static or global variables
    static int i0=0; // actual start for drawing
    static bool _copy_data=true; // flag that new samples need to be copied
    static int level=35; // trigger level value datatype should be the same as your samples...
    
    int i,j;
    for (;;)
    {
    // copy new samples to buffer if needed
    if (_copy_data)
    for (_copy_data=false,i=0,j=0;i<countSamples;++j)
    {
    YVectorRight[j]=Samples[i++];
    YVectorLeft[j] =Samples[i++];
    }
    // now search for new start
    for (i=i0+1;i<countSamples>>1;i++)
    if (YVectorLeft[i-1]<level) // lower then level before i
    if (YVectorLeft[i]>=level) // higher then level after i
    {
    i0=i;
    break;
    }
    if (i0>=(countSamples>>1)-view_samples) { i0=0; _copy_data=true; continue; }
    break;
    }
    // here draw or FFT,draw  buffers YVectorRight,YVectorLeft from i0 position
    
    • view_samples размер просматриваемых / обрабатываемых данных (для одного или нескольких экранов) должен быть в несколько раз меньше (countSamples>>1)
    • этот код может потерять один экран в граничной области, чтобы избежать необходимости использовать циклические буферы.
    • просто закодируйте все условия триггера с помощью оператора if или switch
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]