Síntesis comparada I (hola-mundo II)

grainsinth
#31 por grainsinth el 01/06/2006
Perdón se me había olvidado que querías que la caída fuera exponencial. He cambiado la función line por la curve que nos da ese descenso.

Imagen no disponible
Subir
Robakun
#32 por Robakun el 15/06/2006
Estupendo el ejemplo de de Max y el de haskell (:D), cuando pueda espero añadir alguno más...os animais con reaktor, synthedit, o cualquier otro synte?

En el próximo "syntesis comparada" se podría usar una tabla de ondas para sumar armónicos, qué os parece?
Subir
avelino
#33 por avelino el 19/06/2006
Mi humilde contribución en ANSI-C
[code]#include
#include
#include
#include

#define F_MUEST 44100 /* frecuencia de muetreo: 44.1 KHz */
#define TIEMPO 1 /* segundos de reproducción */
#define MUESTRAS_TOTALES (TIEMPO * F_MUEST)
#define NUM_PARCIALES 7 /* 7 parciales */

signed short int salida[MUESTRAS_TOTALES];
unsigned int frecuencias[NUM_PARCIALES] = {240, 277, 385, 605, 340, 670, 812};
float amplitudes[NUM_PARCIALES] = {1, 0.83, 0.66, 0.33, 0.33, 0.33, 0.33};

int main(void) {
int i, j;
int fd;
float v, final_v;

fd = 1;
for (i = 0; i < MUESTRAS_TOTALES; i++) {
/* sumamos todas las componentes */
v = 0;
for (j = 0; j < NUM_PARCIALES; j++) {
float aux = cos(2 * M_PI * ((float)i / F_MUEST) * frecuencias[j]);
v += aux * amplitudes[j];
}
/* envolvente exponencial a toda la señal */
final_v = v * (float) exp(-(float)i / F_MUEST);
/* limitador */
if (final_v > 1.0)
final_v = 1.0;
else if (final_v < -1.0)
final_v = -1.0;
/* conversor float --> signed short int */
salida = (signed short int) rint(final_v * 32767);
}
write(fd, salida, MUESTRAS_TOTALES * sizeof(signed short int));
return 0;
}
[/code]
Envía la señal a la salida estándar. Formato crudo 16 bit con signo mono.
Subir
palurdo
#34 por palurdo el 02/07/2006
He hecho este segundo hola mundo en 2 sintes.

El primero, no sé si habeis oido hablar de él, es el "Visual Orangator", ocupa apenas medio mega, y es sucesor del famosísimo por aquel entonces "Orangator", el que podía generar cualquier sonido si eras capáz de configurarlo. La diferencia principal entre Orangator y Visual Orangator, es que éste es modular (aunque con menos opciones que su padre).

Aquí os pongo una captura:

Imagen no disponible

El módulo de arriba es un generador lineal de envolvente, que a pesar de su nombre, se puede configurar para que la caída tenga forma exponencial (yo he puesto un valor de curva de sqrt(3)=1.7320 que se asemeja bastante). Además le he puesto una ganancia de 30% (en lugar del 100%) para que no sature la suma de los osciladores.
Esta envolvente controla la amplitud de los 7 osciladores, cada uno configurado con los parámetros y ganancias especificadas. Las salidas se suman en 2 mezcladores (se necesitan 2 para cubrir 7 entradas) y la salida mezclada se envía al dispositivo de salida (altavoz, o disco, dependiendo del caso).

Para escuchar el resultado:

Ding.mp3

Para descargarse los parámetros, y el programa:

Ding-VO
Visual Orangator

El segundo sinte que he utilizado, os puedo asegurar que nunca habeis oido hablar de él. Es un programa que desarrollé hace 2 años para estudiar desde la perspectiva del Audio, la generación de secuencias caóticas. Sin embargo, a pesar de ser un programa muy simple, he hecho cosas curiosas con él. Esta es la primera vez que lo publico en internet.

Este programa utiliza un lenguaje muy sencillo para generar las secuencias de audio. Os pongo aquí el Script del Hola Mundo II:

[code]descripcion
>Este script genera un "Ding" compuesto por 7 senoidales.
>La señal se amortigua por una exponencial.
>
>Para que salga bien, hay que configurar GISA para que
>se generen 6 segundos de secuencia de audio.
>
>Los parametros que se pueden modificar son:
>
> Amplitud(a): Amplitud de la secuencia de salida
> Recomendado: -0.30 secuencia de salida. Recomendado 0.99991, la
> secuencia se autoamplifica hasta la saturacion.
>
>Sobre este ejercicio en:
> https://www.hispasonic.com/foros/sintesis-comparada-i-hola-mundo-ii/101055
fin

variable a,r,y,d,o

entrada(a,"Amplitud Global",0.30)
entrada(r,"Amortiguamiento",0.99997)

>inicializamos el decaimiento de la señal (estado inicial de la
>exponencial)
d=1

iterar

>sumamos las siete ondas con sus respectivas frecuencias y
>amplitudes. ITER es la iteración actual, y FM es la
>frecuencia de muestreo introducida desde el programa.
y=sin(2*pi*240*ITER/FM)
y=y+0.83*sin(2*pi*277*ITER/FM)
y=y+0.66*sin(2*pi*385*ITER/FM)
y=y+0.33*sin(2*pi*605*ITER/FM)
y=y+0.33*sin(2*pi*340*ITER/FM)
y=y+0.33*sin(2*pi*670*ITER/FM)
y=y+0.33*sin(2*pi*812*ITER/FM)

>Multiplicamos por la amplitud y el decaimiento exponencial.
y=a*d*y

>Multiplicar en cada iteración (t) el decaimiento "d", por el factor de
>amortiguación "r" es como hacer d(t)=d(0)*exp(log(r)*t)
d=d*r

>escalamos la salida para grabarla en formato de 16 bits.
o=32767*y

>grabamos el resultado de cada iteración en el archivo WAV
grabar(o)

fin
[/code]

Mi programa, llamado "Generador Iterativo de Secuencias de Audio", o GISA, y que incluye los Hola Mundo I y II de hispasonic, lo podeis bajar desde aquí:

GISA V1.0

El archivo de sonido generado:

Ding-GISA.mp3

Bueno, espero que os gusten estos ejemplos. Un saludo.
Archivos adjuntos ( para descargar)
GISA V1.0.zip
Subir
avelino
#35 por avelino el 03/07/2006
Muy útil la utilidad GISA esta ;-). Enhorabuena :-)
Subir
palurdo
#36 por palurdo el 03/07/2006
La has probado?? que tal te funciona?
Subir
avelino
#37 por avelino el 04/07/2006
El juicio de "util" lo emití viendo el código fuente, que es muy claro y permite implementar de forma rápida y sencilla algoritmos de síntesis y procesado de audio ;-)
Hombre, lo probaría si, al menos fuera un programa de DOS. Porque uso Linux y el emulador de DOS que tengo, el dosbox, al ejecutarlo me da el consabido mensaje de error "This program cannot be run in DOS mode" :-(. El emulador de windows que tengo no me funciona en el ordenata de la ofi (desde donde lo intenté probar) así que nada... :-(.
¿Has pensado en liberar el código fuente? ¿En qué lenguaje lo tienes hecho? ¿Usa ventanas o es un programa de línea de comandos?
Subir
Robakun
#38 por Robakun el 04/07/2006
Hola palurdo :roll: , estupendo orangator. Recuerda a un programa similar en linux y windows que se llama gALAN ( http://galan.sourceforge.net/ )

Pues Gisa tiene buena pinta, el código como dice avelino es muy claro e instructivo. Lo he probado en Ubuntu dapper y funciona muy bien.

Imagen no disponible

Enhorabuena por el trabajo, y te invito a que sigas poniendo ejemplos.
Subir
Robakun
#39 por Robakun el 04/07/2006
Pseudocódigo o esquema general de lo que venimos haciendo.

Imagen no disponible
(realizado con el software Dia)

Esto me hace imaginar lo siguiente. La forma de pensar y actuar en el software libre, llevado al mundo del sonido, invitaria a divulgar "cómo construir un sonido de forma genérica". Eso ya puede hacerse, por ejemplo mostrando a los demás "cómo se hace en tu programa favorito, ese sonido que tanto te gusta".Pero para que fuera realmente interesante, hay que presentar los esquemas en un lenguaje/sistema/esquema que no dependa de una empresa particular, para que sea de acceso posible a todas las personas, independientemente del sistema que usen.

No se si se entiende lo que intento expresar. Un problema (o bendición según se mire) es que no hay una forma única de anotar un esquema de síntesis sonora. Frecuentemente se usan los diagramas del tipo que he puesto más arriba.
Subir
palurdo
#40 por palurdo el 04/07/2006
Pues resulta que me estaba preguntando si mi programa sería capaz de sintetizar una simulación de barrido de resonancia a partir de modulación por distorsión de fase, siguiendo un esquema similar a este:

Imagen no disponible

Fuente: Wikipedia - Síntesis por distorsión de fase

El principio de funcionamiento es el siguiente:

Tenemos una rampa de frecuencia base.

Tenemos una onda que varía en frecuencia pero que se sincroniza a cero cada vez que comienza la rampa. Entonces tras el salto de la rampa aparece, en la onda, un salto puesto que se sincroniza de nuevo a cero con el comienzo de la rampa.

Si invertimos la rampa para hacerla descendente y la multiplicamos por la onda, cuando esta onda vaya a saltar, la rampa hará que en el salto el valor de la onda sea 0, por lo que el salto desaparece.

En realidad la función de Rampa base puede ser cualquier función de ventana que termine en 0 (e incluso es mejor que además empieze en 0), de esa forma tenemos una onda base cuyos armónicos varían conforme varía la frecuencia de la onda del barrido, simulando el barrido de resonancia.

Entonces se me ha planteado un problema. Resulta que en mi programa no era capaz de programar este algoritmo por una sencilla razón; para poder sincronizar las 2 ondas tenía que poder detectar cuando empezaba la ventana de base, y para eso tenía que usar alguna función que me permitiera comparar valores. Bueno, pues como el evaluador de expresiones no incluía operadores lógicos y de comparación (&,|,!,>,>=,en fase deformando una senoidal en forma de barrido
>que conformará los armónicos de la señal resultante.
>
>El resultado es muy melódico.
>
>Los parametros que se pueden modificar son:
>
> Amplitud(a): Amplitud de la secuencia de salida
> Recomendado: -1 la secuencia de base. Recomendado: 0 inicio del barrido de la simulación de resonancia.
> Recomendado: 0 fín del barrido de la simulación de resonancia.
> Recomendado: 0 secuencia de salida. Recomendado 0.9991, la
> secuencia se autoamplifica hasta la saturacion.
fin

variable a,y,r,b,o,f,f1,f2,c,y1,ax,ay,ay1,dz

entrada(f,"Frecuencia Base [Hz]",440)
entrada(f1,"Frecuencia Inicial [Hz]",200);
entrada(f2,"Frecuencia Final [Hz]",10000);
entrada(a,"Amplitud",1)
entrada(r,"Amortiguamiento",0.99985)

>Inicializamos variables:

>f2 pasa a ser el incremento de f del barrido
f2=(f2-f1)/MAXITER

>b es el incremento de paso de la rampa periodica
>(la rampa pasa de 0 a 1 cada f/FM ciclos)
b=f/FM

>El contador que sincroniza la rampa con la senoidal.
c=0
>La distancia del cero con respecto al polo del filtro pasaaltos.
dz=1-(768/FM)

iterar

>calculamos la rampa periodica sumando el incremento
y=y+b

>si se llega al final de la rampa (la salida pasa a ser mayor de 1),
>se resetea el contador de la senoidal.
c=c*(yHacer el módulo de 1 en coma flotante equivale a quitar la parte entera.
y=y%1

>Creamos la rampa descendiente. Al multiplicarla después por la ascendiente
>crearemos una ventana parabólica positiva (que comienza y termina en 0 en
>cada ciclo de la frecuencia de base.
y1=1-y

>Multiplicamos la ventana por el segmento de senoidal y aplicamos ganancias.
o=a*4*y1*y*sin(2*pi*f1*c/FM)*32767

>Actualizamos el amortiguamiento como la degeneración pregresiva de la ganancia.
a=a*r

>actualizamos contador de la senoidal (se incrementará mientras la rampa no
>llegue al final).
c=c+1

>Actualizamos la f de barrido para cada punto (añadiendo el incremento).
f1=f1+f2

>Todo esto lo pasamos por el filtro pasaaltos para quitar el nivel de continua.
ay = o - ax + dz * ay1
ax = o
ay1=ay

>y grabamos la salida del filtro.
grabar(ay)

fin
[/code]

Darse cuenta que aquí la clave para sincronizar las 2 ondas es la parte de la operación (yEste script genera una senoidal cúbica
>en fase deformando una senoidal en forma de barrido
>que conformará los armónicos de la señal resultante.
>
>El resultado es muy melódico.
>
>Los parametros que se pueden modificar son:
>
> Amplitud(a): Amplitud de la secuencia de salida
> Recomendado: -1 la secuencia de base. Recomendado: 0 inicio del barrido de la simulación de resonancia.
> Recomendado: 0 fín del barrido de la simulación de resonancia.
> Recomendado: 0 secuencia de salida. Recomendado 0.9991, la
> secuencia se autoamplifica hasta la saturacion.
fin

variable a,y,r,b,o,f,f1,f2,c,y1

entrada(f,"Frecuencia Base [Hz]",440)
entrada(f1,"Frecuencia Inicial [Hz]",200);
entrada(f2,"Frecuencia Final [Hz]",10000);
entrada(a,"Amplitud",1)
entrada(r,"Amortiguamiento",0.99985)

>Inicializamos variables:

>f2 pasa a ser el incremento de f del barrido
f2=(f2-f1)/MAXITER

>El contador que sincroniza la ventana con la senoidal.
c=0

iterar

>calculamos el seno cúbico periodico y guardamos el valor anterior y1.
y1=y
y=sin(2*pi*f*ITER/FM)^3

>si se cruza por cero (y*y1 es negativo), se sincroniza la cuenta de la senoidal de barrido.
c=c*(y*y1>0)

>Multiplicamos la ventana por el segmento de senoidal y aplicamos ganancias.
o=a*y*sin(2*pi*f1*c/FM)*32767


>Actualizamos el amortiguamiento como la degeneración pregresiva de la ganancia.
a=a*r

>actualizamos contador de la senoidal de los armónicos (se incrementará mientras
>la senoidal de base no cruze por cero).
c=c+1

>Actualizamos la f de barrido para cada punto (añadiendo el incremento).
f1=f1+f2

>Grabamos la salida
grabar(o)

fin
[/code]

Aquí la clave para sincronizar es saber cuando la señal de base cruza por 0 (y eso pasa
cada vez que hay un cambio de signo entre un valor y el anterior, cuya multiplicación será menor que 0), para resetear el contador de la senoidal de barrido.

Cuando vaya actualizando el programa ya lo iré mencionando por aquí. La verdad es que no pensé en un sintetizador cuando programé este programa, sino un programa que generara secuencias de sonido a partir de funciones matemáticas iterativas, para su posterior análisis, aunque la verdad, de una cosa a otra no hay mucha diferencia, no?, además, están saliendo cosas bastante curiosas de este programa (sólo hay que ver los ejemplos listados en este post, jeje).

De todas formas el programa todavía tiene muchos fallos que tengo que corregir, y nuevas caracteristicas que tengo que implementar, como por ejemplo vectores, etc.
Archivos adjuntos ( para descargar)
GISA V1.0.1.zip
Subir
Robakun
#41 por Robakun el 06/07/2006
Hola palurdo, tu programa va cobrando interés. Te sugiero una cosa, abre otro hilo sobre tu programa, en el que vas dando noticia de las nuevas versiones y mejoras. Así también mantenemos un orden y dedicamos este hilo sólo al ejercicio propuesto. Si no, nos liamos .¿Qué te parece?

Enhorabuena y un saludo
Subir
Hilos similares
Nuevo post

Regístrate o para poder postear en este hilo