c++ - trazando datos en tiempo real en(qwt) Oscillocope
matplotlib c++ (1)
Hehe hizo esto hace unos años para los estudiantes durante la clase. Espero que sepas cómo funcionan los osciloscopios, así que estos son solo los conceptos básicos:
base de tiempo
-
fsmpl
es la frecuencia de muestreo de la señal de entrada [Hz]
Trate de usar lo más grande posible
(44100,48000, ???)
por lo que la frecuencia máxima detectada es entoncesfsmpl/2
esto le da la parte superior de su eje de base de tiempo. El límite bajo viene dado por la longitud de tu buffer-
dibujar
Crea una función que renderizará tu buffer de muestreo desde la dirección de inicio especificada (dentro del buffer) con:
- Escala Y ... ajuste de amplitud
- Desplazamiento en Y ... Posición del haz vertical
- X-offset ... Time shift o posición horizontal
Esto se puede hacer modificando la dirección de inicio o simplemente compensando X la curva
Nivel
Crear una función que emulará la funcionalidad de nivel . Así que busque el búfer desde la dirección de inicio y deténgalo si la amplitud cruza el nivel. Puede tener más modos, pero estos son conceptos básicos que debe implementar:
- amplitud:
( < lvl ) -> ( > lvl )
- amplitud:
( > lvl ) -> ( < lvl )
Hay muchas otras posibilidades para nivel como error, borde relativo, ...
- amplitud:
Avance
Puede poner todo esto junto, por ejemplo, así: tiene una variable de
start address
para que muestre los datos en un búfer de forma continua y en ellevel
llamada del temporizador con lastart address
(y actualícelo). Luego llame al sorteo con una nuevastart address
y agregue eltimebase period
parastart address
(por supuesto en términos de sus muestras)multicanal
Uso Line IN así que tengo entrada estéreo (A, B = izquierda, derecha) por lo tanto, puedo agregar algunas otras cosas como:
- Fuente de nivel (
A,B
, ninguno) - modo de renderizado (base de tiempo, Chebyshev (curva de Lissajous si está cerrado))
- Chebyshev =
x
axis esA
,y
eje esB
crea imágenes famosas de Chebyshev que son buenas para señales sinusoidales dependientes. Normalmente forma círculos, elipses, bucles distorsionados ...
- Fuente de nivel (
miscel cosas
Puede agregar filtros para canales que emulan capacitancia o toma de tierra de entrada y mucho más
GUI
Necesitas muchas configuraciones. Prefiero perillas analógicas en lugar de botones / barras de desplazamiento / deslizadores como en un osciloscopio real.
- (semi) Valores analógicos: Amplitud, TimeBase, Nivel, X-offset, Y-offset
- valores discretos: modo de nivel (/,), fuente de nivel (A, B, -), cada canal (directo, tierra, apagado, capacidad activada)
Aquí hay algunas capturas de pantalla de mi osciloscopio:
Aquí está la captura de pantalla de mi generador:
Y finalmente después de agregar algo de FFT también Spectrum Analyzer
PD.
- Empecé con DirectSound, pero es una mierda porque tiene devoluciones de llamada de buffer defectuosas / no funcionales
- Uso WinAPI WaveIn / Out para todo el sonido en mis aplicaciones ahora. Después de algunos caprichos, es lo mejor para mis necesidades y tiene la mejor latencia (Directsound es demasiado lento más de 10 veces) pero para osciloscopio no tiene mérito (necesito baja latencia sobre todo para emuladores)
Por cierto. Tengo estas tres aplicaciones como clases de subventana de C ++ vinculables (Borland)
- y utilizado por última vez con mi emulador ATMega168 para mi depuración del controlador BLDC sin sensores
- aquí puedes probar mi Osciloscopio, generador y analizador de espectro. Si te confunden con la descarga, lee los comentarios a continuación. Esta contraseña de btw es: "oscill"
Espero que te sirva de ayuda si necesitas ayuda con algo solo coméntame
[Editar1] desencadenar
Dispare todos los canales a la vez, pero la condición del activador se comprueba generalmente desde uno. Ahora la implementación es simple, por ejemplo, permita que la condición de activación sea el canal A (izquierda) que se eleva por encima del nivel, de modo que:
Primero haz una reproducción continua sin ningún gatillo que hayas escrito, es así:
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
Añadir disparador
Para agregar la condición de activación, solo encuentra la muestra que se encuentra con ella y comienza a dibujar a partir de la misma para que la cambie a algo como esto
// 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
- el
view_samples
es el tamaño de datos visto / procesado (para una o más pantallas) debe ser pocas veces menor que el(countSamples>>1)
- este código puede perder una pantalla en el área del borde para evitar que necesite implementar buffers cíclicos bot para principiantes, incluso esto está bien
- solo codifica todas las condiciones de activación a través de alguna instrucción if o switch
- el
Estoy tratando de crear un programa, usando Qt (c ++), que puede grabar audio desde mi micrófono usando QAudioinput y QIODevice. Ahora, quiero visualizar mi señal
Cualquier ayuda sería apreciada. Gracias
[Editar1] - copiado de tu comentario (por Spektre)
- Tengo solo un Buffer para ambos canales
- Uso Qt, el valor del canal está entrelazado en el búfer
así es como yo separé los valores
for ( int i = 0, j = 0; i < countSamples ; ++j) { YVectorRight[j]=Samples[i++]; YVectorLeft[j] =Samples[i++]; }
después de trazar YvectorRight y YvectorLeft. No veo cómo activar solo un canal