Universidad de Buenos Aires Facultad De Ingenierı́a Año 2012 - 1er Cuatrimestre Algoritmos y Programación I (75.02) TRABAJO PRÁCTICO Nº 3 TEMA: Sintetizador de música FECHA: 30 de agosto de 2012 INTEGRANTES: Ferrari Bihurriet, Francisco - #92275 <franferra 09 90@hotmail.com> Arias, Francisco Nicolas - #93459 <ariasfrancisco91@yahoo.com> 75.02 - Algoritmos y Programación I Ing. Martı́n Cardozo ÍNDICE Índice 1. Enunciado 3 2. Estructura Funcional 11 3. Consideraciones y Estrategias 12 3.1. Validación de datos y lectura de archivos de entrada . . . . . . . . . . . . . 12 3.2. Sı́ntesis del sonido . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 3.3. Escritura en del archivo de salida en formato WAV . . . . . . . . . . . . . 12 4. Resultados de ejecución 13 4.1. En condiciones inesperadas de entrada . . . . . . . . . . . . . . . . . . . . 13 4.2. En condiciones normales de entrada . . . . . . . . . . . . . . . . . . . . . . 15 5. Problemas encontrados en el desarrollo 17 5.1. Optimización del tiempo de sı́ntesis . . . . . . . . . . . . . . . . . . . . . . 17 5.2. Funciones de modulación incorrectas . . . . . . . . . . . . . . . . . . . . . 18 6. Conclusiones 18 7. Bibliografı́a consultada 18 8. Códigos fuente 8.1. ADT musical score . . . . . . . . . . . 8.1.1. ADT musical score.h . . . . . . 8.1.2. ADT musical score PRIVATE.h 8.1.3. ADT musical score.c . . . . . . 8.2. ADT synthesizer . . . . . . . . . . . . 8.2.1. modulationlib.h . . . . . . . . . 8.2.2. modulationlib.c . . . . . . . . . 8.2.3. ADT synthesizer.h . . . . . . . 8.2.4. ADT synthesizer PRIVATE.h . 8.2.5. ADT synthesizer.c . . . . . . . 8.3. ADT wav file . . . . . . . . . . . . . . 8.3.1. ADT wav file.h . . . . . . . . . 8.3.2. ADT wav file PRIVATE.h . . . 8.3.3. ADT wav file.c . . . . . . . . . 8.4. main modules . . . . . . . . . . . . . . 8.4.1. addsynthlib.h . . . . . . . . . . 8.4.2. addsynthlib.c . . . . . . . . . . 8.4.3. common.h . . . . . . . . . . . . 8.4.4. main.c . . . . . . . . . . . . . . 8.5. langs . . . . . . . . . . . . . . . . . . . 8.5.1. msgs dictionary es.c . . . . . . 8.5.2. msgs dictionary en.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 19 19 20 22 27 27 28 31 32 34 40 40 40 42 44 44 45 48 50 55 55 56 1 ÍNDICE 8.6. Makefile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 8.6.1. Makefile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 8.6.2. lang . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 2 1 Enunciado 1. Enunciado Trabajo Práctico N◦3 - Sintetizador de música 1. Objetivo del TP El objetivo del presente trabajo consiste en la realización de un aplicativo en modo consola, escrito en ANSI-C89, que secuencie archivos WAVE en base a la especificación de un sintetizador y una partitura musical. 2. Alcance del TP Mediante el presente TP se busca que el Estudiante adquiera y aplique conocimientos sobre los siguientes temas: Argumentos en Lı́nea de Ordenes (CLA). Makefile y proyectos modularizados. TDAs. Memoria dinámica. Archivos de texto y binarios. Formato WAVE (audio). Punteros a Funciones. 3. Introducción 3.1. El sonido La percepción que sentimos como sonido se debe a la vibración de ondas en el aire que es sensada por nuestros oidos. En los sonidos podemos distinguir una intensidad, por la cual hay sonidos más fuertes que otros; un tono, por el cual hay sonidos más agudos y sonidos más graves; y un timbre, por el cual no todas las cosas que tienen el mismo tono suenan igual. Supongamos una onda de 110Hz que oscila durante un cuarto de segundo (Fig. 1). Esta onda es sencilla de concebir matemáticamente, pero es imposible de obtener por medios fı́sicos. Una onda fı́sica no podrı́a comenzar a oscilar instantáneamente, ni tampoco podrı́a atenuarse inmediatamente. Si oyéramos una onda de esas caracterı́sticas, percibirı́amos un chasquido al comienzo y al final de la misma1 . Una onda producida por un elemento fı́sico tendrá un incremento paulatino hasta su máximo producido por el ataque y su entrada en resonancia, irá apaciguándose por disipación de energı́a durante el sostenido, 1 Le dejamos hacer al Análisis de Fourier las cuentas pertinentes. 1 3 1 Enunciado Algoritmos y Programación I (75.02) – Trabajo Práctico N◦ 3 – 1er Cuatr. 2012 1 0.5 0 -0.5 -1 -0.05 0 0.05 0.1 0.15 0.2 0.25 0.3 0.25 0.3 Figura 1: Onda sinusoidal de 110Hz de duración 0,25s. 1 0.5 0 -0.5 -1 -0.05 0 0.05 0.1 0.15 0.2 Figura 2: 0 < t < 0,05: Ataque. 0,05 < t < 0,25: Sostenido. t > 0,25: Decaimiento. y luego tardará unos instantes en volverse a poner en reposo durante el decaimiento (Fig. 2). Hasta ahora tenemos una onda pura y, como ya deberı́a ser predecible, tampoco las ondas puras son lo que abunda en la naturaleza2 . La mayor parte de los dispositivos, además de vibrar con la frecuencia fundamental que percibimos como tono vibran en múltiplos de la misma, llamados armónicos o en frecuencias parásitas. Ni siquiera instrumentos como un diapasón son capaces de entregar un sonido puro. Las ondas generadas por un instrumento oscilarán a una frecuencia dada por su tono, y generarán resonancias en diferentes armónicos con menor amplitud (Fig. 3). Juntando el tono, dado por la frecuencia fundamental; la intensidad, modulada por el ataque-sostenido-decaimiento y el timbre, dado por la adición de armónicos; una onda de 110Hz producida por un instrumento real, tendrı́a un aspecto similar al de la Figura 4. 2 ¡Por suerte!, un aburrido ejemplo cotidiano de sonido puro son los pulsos del teléfono. 1 0.5 0 -0.5 -1 0 0.001 0.002 0.003 0.004 0.005 0.006 0.007 0.008 0.009 Figura 3: Sı́ntesis aditiva de una onda (rojo) en base a una frecuencia fundamental de 110Hz (verde) y 7 armónicos (azules). Este timbre podrı́a imitar el de una flauta. 2 4 1 Enunciado Algoritmos y Programación I (75.02) – Trabajo Práctico N◦ 3 – 1er Cuatr. 2012 1 0.5 0 -0.5 -1 -0.05 0 0.05 0.1 0.15 0.2 0.25 0.3 Figura 4: Onda de 110Hz sintetizada en tono, intensidad y timbre. Nota La La] Si Do Do] Re Re] Mi Fa Fa] Sol Sol] La Cifrado americano A A] – B[ B C C] – D[ D D] – E[ E F F] – G[ G G] – A[ A Octava 4 4 4 4 4 4 4 4 4 4 4 4 5 Frecuencia (Hz) 220,000 233,082 246,942 261,626 277,183 293,665 311,127 329,629 349,228 369,994 391,995 415,305 440,000 Tabla 1: Frecuencias para la cuarta octava (afinación 440). 3.2. La escala musical La música se genera en base a sonidos. Ahora bien, para que la misma suene agradable al oido, se construyen escalas que fijan qué tonos están permitidos. Todas las escalas se construyen en base a particiones de la octava, y luego se replican en las octavas subsiguientes3 . Se considera que hay una octava entre dos notas donde una duplica la frecuencia de la otra. Las escalas occidentales son dodecafónicas, se construyen en base a 12 particiones equidistantes de una octava4 . Además, se fija que la nota La de la quinta octava oscila a 440Hz5 . Las notas de la escala son Do, Do] (ó Re[6 ), Re, Re] (ó Mi[), Mi, Fa, Fa] (ó Sol[), Sol, Sol] (ó La[), La, La] (ó Si[) y Si, en ese orden. Por razones de simplificar la notación, introduciremos el cifrado americano. En el mismo a cada nota se le asigna una letra entre la A y la G, comenzando por la nota La y continuando cı́clicamente a la octava siguiente. Sabiendo que hay 12 notas, equidistantes exponencialmente7 , que el La de la quinta se fija en 440Hz, que las octavas avanzan duplicando, y el nombre de las notas, podemos reconstruir la frecuencia para cualquier nota dada. La Tabla 1 muestra un ejemplo de ello. 3 Para esto y lo demás que desarrollemos en el capı́tulo, le pasamos a Pitágoras el fardo de dar las explicaciones. 4 Más o menos, y si bien esto no es válido para la teorı́a estricta o para algunos instrumentos, sı́ lo es para la mayorı́a. 5 Si el comité ISO lo dice, no vamos a contradecirlo. 6 Otra vez, sin ponerse exquisitos ni dar vueltas innecesarias con comas y otras yerbas. √ 7 Es decir, si una nota tiene frecuencia f , la nota siguiente tendrá frecuencia f · 12 2. 3 5 1 Enunciado Algoritmos y Programación I (75.02) – Trabajo Práctico N◦ 3 – 1er Cuatr. 2012 char[4] uint32 char[4] char[4] uint32 uint16 uint16 uint32 uint32 uint16 uint16 char[4] uint32 ChunkId ChunkSize Format Subchunk1ID Subchukn1Size AudioFormat NumChannels SampleRate ByteRate BlockAlign BitsPerSample SubChunk2ID SubChunk2Size int16[n] Data Vale "RIFF" 36 + 2n Vale "WAVE" Vale "fmt " Vale 16 Vale 1 Vale 1 8000, 44100, etc. 2 × SampleRate Vale 16 Vale 16 Vale "data" 2n Secuencia de n muestras Figura 5: Contenido binario de un archivo WAVE PCM monoaural de 16bits. 3.3. El formato WAVE El formato WAVE forma parte de la especificación RIFF de Microsoft. El mismo permite almacenar en modo raw sin compresión muestras de audio. Un archivo WAVE es un archivo binario compuesto por un preámbulo, y dos chunks. El primero de ellos es de tamaño fijo, y contiene la información acerca de las caracterı́sticas del track ; mientras que el segundo contiene las muestras de audio que componen al mismo. Para este trabajo se utilizará la compresión PCM (esto es, sin compresión), 16 bits de resolución y formato monoaural. El contenido binario de un archivo WAVE de estas caracterı́sticas es el de la Tabla 5. Tanto los números de 16 bits como de 32 en el formato WAVE, se almacenan en el archivo en formato little endian. Las muestras se almacenan como enteros de 16 bits en complemento a 2, puede asumirse que es el mismo formato que utiliza C. No puede asumirse bajo ningún punto de vista el endianness de la plataforma. 4. Desarrollo del TP El trabajo práctico consistirá en un ejecutable en modo consola que pueda realizar la sı́ntesis sobre un archivo WAVE en base a la configuración de un sintetizador y una secuencia de notas. La sintáxis de ejecución será: $ ./sintetizador [-f <frecuencia>] -p <partitura.txt> -s <sintetizador.txt> -o <audio.wav> > sintetizador [-f <frecuencia>] -p <partitura.txt> -s <sintetizador.txt> -o <audio.wav> La especificación de los parámetros se encuentra en la Tabla 2. 4.1. Archivo de partitura El archivo de partitura, será un archivo ASCII donde cada lı́nea representará una nota a ser ejecutada. Cada lı́nea contendrá un tiempo de inicio de la ejecución de la nota, la nota a interpretar y la duración. Todos los tiempos se especificarán en segundos. Las notas se 4 6 1 Enunciado Algoritmos y Programación I (75.02) – Trabajo Práctico N◦ 3 – 1er Cuatr. 2012 Parámetro -p -s -o -f Valores Nombre del archivo de entrada que describe la partitura. Nombre del archivo de entrada que describe el sintetizador. Nombre del archivo de salida WAVE. Frecuencia de muestreo. Una de: 8000, 9600, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 88200, 96000. (optativo) Tabla 2: Parámetros de CLA. especificarán en cifrado americano, utilizando el sufijo “s” para notas sostenidas (]) y “b” para notas bemoles ([) y su octava correspondiente. Por ejemplo: 0 A4 .5 .5 Bb4 .5 1 B4 .5 1.5 C4 .5 2 Cs4 .5 2.5 D4 .5 Describe una secuencia de semitonos de medio segundo de duración, desde el La hasta el Re de la cuarta octava. La duración de la ejecución del fragmento será de 3 segundos. En el archivo se desconoce la cantidad de notas a ejecutar, y no es requisito que el mismo venga ordenado cronológicamente (tampoco hace falta). 4.2. Archivo de sintetizador El archivo de sintetizador, será un archivo ASCII con información sobre los armónicos, y las envolventes para modular la amplitud. El archivo de sintetizador estará dividido en cuatro partes: Armónicos, donde se especificará el número de armónicos y luego pares de múltiplo e intensidad. Ataque, donde se especificará el tipo de ataque y luego los parámetros. Sostenido, donde se especificará el tipo de sostenido y luego los parámetros. Decaimiento, donde se especificará el tipo de decaimiento y luego los parámetros. Los moduladores de amplitud serán alguno de los de la Tabla 3. Por ejemplo, un archivo de sintetizador podrı́a tener este contenido: 8 1 0.577501 2 0.577501 3 0.063525 4 0.127050 5 0.103950 6 0.011550 7 0.011550 8 0.011550 TRI 0.05 0.03 1.3 CONSTANT INVLINEAR .02 5 7 1 Enunciado Algoritmos y Programación I (75.02) – Trabajo Práctico N◦ 3 – 1er Cuatr. 2012 Nombre CONSTANT LINEAR Ecuación f (t) = 1 t f (t) = n t0 o f (t) = máx 1 − tt0 ; 0 f (t) = 1 + a sen(f t) INVLINEAR SIN f (t) = e EXP −5t INVEXP QUARTCOS QUARTSIN HALFCOS HALFSIN LOG INVLOG TRI PULSES 5(t−t0 ) t0 f (t) = et0 πt f (t) = cos 2t 0 πt f (t) = sen 2t 0 1+cos πt t0 f (t) = 2 1+sen π tt − 12 0 f (t) = 2 f (t) = log10 9t t0 + 1 −9t log10 t +10 t<t0 , 0 f (t) = 0 t≥t0 . ta1 t<t1 , t1 f (t) = t−t1 t1 −t0 + a1 t>t1 . o n 0 1 0 t t f (t0 ) = mı́n | 1−a t1 (t − t0 + t1 )| + a1 ; 1 ,t = t0 −b t0 c Parámetros – t0 Uso en S A t0 a, f S, D S t0 A t0 S, D t0 S, D t0 A t0 S, D t0 A t0 A t0 S, D t0 , t1 , a1 A t0 , t1 , a1 S Tabla 3: Moduladores de amplitud. Para su uso en A: Ataque, S: Sostenido, D: Decaimiento. En él se define la progresión de 8 armónicos en octavas8 , un ataque TRI de duración 0,05s, un sostenido CONSTANT y un decaimiento INVLINEAR de duración 0,02s. 4.3. Sı́ntesis La sı́ntesis del sonido se realizará para cada nota por separado, realizando una adición sobre el audio de las demás notas. Dada una nota que comienza en el instante t0 , de frecuencia f y duración d, con un sintetizador con una serie de n armónicos donde están definidos sus múltiplos Mi y sus intensidades Ii , además de sus funciones de ataque fa , sostenimiento fs y decaimiento fd , se procede como sigue. El timbre del instrumento se obtiene de computar la siguiente expresión: y(t) = n X i=1 Ii sen (2πf Mi (t − t0 )) Esto nos da una señal infinita, la misma será ajustada según la modulación de amplitud. La modulación de amplitud se compone por la concatenación de ataque, sostenido y decaimiento. Antes de explicar cómo se combinan, vale observar que todas las funciones para ser usadas como ataque, recorren un camino de 0 a 1 en un tiempo t0 , todas las funciones de decaimiento recorren el camino inverso en un tiempo t0 , y todas las funciones de sostenido comienzan en 1 y son siempre positivas. Esto es importante para comprender cómo se las empalma. Una nota no puede durar nunca menos que el tiempo de ataque ta , una vez finalizada la nota, se ejecuta el decaimiento, de tiempo td . Luego, la función de modulación 8 Estos armónicos, casualmente, son los mismos de la Figura 3. 6 8 1 Enunciado Algoritmos y Programación I (75.02) – Trabajo Práctico N◦ 3 – 1er Cuatr. 2012 estará dada por: fa (t − t0 ) t0 < t < t0 + ta f (t − (t + t )) t0 + ta < t < t 0 + d s 0 a m(t) = fs (t0 + d)fd (t − (t0 + d)) t0 + d < t < t0 + d + td 0 Para otro t Observar que la misma es una función continua. Finalmente, la amplitud de la nota estará dada por: a(t) = Ay(t)m(t) Esta función será distinta de cero como mucho en el intervalo t0 < t < t0 + d + td . La constante A debe ser elegida convenientemente para darle el volumen a nuestro instrumento; al elegirla notar que un valor pequeño va a hacer que al truncar sobre 16bits se pierdan muchos valores intermedios, y notar que un valor muy grande puede hacer que la adición de varias notas genere un desbordamiento, lo cual en el audio se va a traducir en una saturación del sonido. El único paso que resta para llevar estas notas a un archivo WAVE es muestrear estas ondas según la frecuencia dada. Dicha discretización debe hacerse en tantas muestras por segundo como las indicadas en la frecuencia de muestreo fm , con t variando en intervalos de 1/fm . 5. Restricciones La realización de los programas pedidos está sujeta a las siguientes restricciones: Deben utilizarse TDAs tanto en los contenedores como en las entidades que ası́ lo requieran. Debe recurrirse al uso de punteros a funciones a fin de parametrizar la elección de los moduladores. Hay ciertas cuestiones que no han sido especificadas intencionalmente en este Requerimiento, para darle al Desarrollador la libertad de elegir implementaciones que, según su criterio, resulten más convenientes en determinadas situaciones. Por lo tanto, se debe explicitar cada una de las decisiones adoptadas, y el o los fundamentos considerados para las mismas. 6. Entrega del Trabajo Práctico Deberá presentarse la correspondiente Documentación de desarrollo del TP impresa y encarpetada, siguiendo la numeración siguiente, incluyendo: 1. Carátula del TP. Incluir una dirección de correo electrónico de contacto. 2. Enunciado del TP. 3. Estructura lógica simplificada de los programas desarrollados (diagramas de flujo). 4. Estructura funcional de los programas desarrollados (Árbol de Funciones). 5. Explicación de cada una de las alternativas consideradas y las estrategias adoptadas. 7 9 1 Enunciado Algoritmos y Programación I (75.02) – Trabajo Práctico N◦ 3 – 1er Cuatr. 2012 6. Resultados de la ejecución (corridas) de los programas, captura de las pantallas, bajo condiciones normales e inesperadas de entrada. 7. Reseña sobre los problemas encontrados en el desarrollo de los programas y las soluciones implementadas para subsanarlos. 8. Conclusiones. NOTA: El Informe deberá ser redactado en correcto idioma castellano, con tipografı́a Times New Roman, Arial, o Verdana, de tamaño 11 para los párrafos, y 13 ó 14 para los tı́tulos. Deberá entregarse una impresión de los códigos fuentes (implementación y headers) de los programas desarrollados. NO entregar archivos de códigos objeto y/o ejecutables. NOTA: Los códigos fuentes deberán ser impresos con tipografı́a Monospace. Deberá entregarse el archivo Makefile del proyecto para el compilador C GCCDJGPP. Deberán entregarse por correo electrónico a la casilla algo7502entregas@gmail.com, todos los archivos fuentes y scripts necesarios para compilar el trabajo práctico, además del informe en formato electrónico. Dicho correo deberá contener en su cuerpo el nombre, apellido y padrón de los integrantes del grupo. De no hacerse la entrega digital en tiempo y forma, el TP no será corregido. SI NO SE PRESENTA CADA UNO DE ESTOS ITEMS, SERÁ RECHAZADO EL TP 7. Bibliografı́a Debe incluirse la referencia a toda bibliografı́a consultada para la realización del presente TP: libros, artı́culos, URLs, etc., citando: Denominación completa del material (Tı́tulo, Autores, Edición, Volumen, etc.). Código ISBN del libro (opcional: código interbibliotecario). URL del sitio consultado. 8 10 2 Estructura Funcional 2. Estructura Funcional main() validate_arguments() status_msg() show_usage() progress_msg() /* ADT_musical_score: 1 */ ADT_musical_score_new() /* ADT_synthesizer: 1 */ ADT_synthesizer_new() /* ADT_musical_score: 9 */ ADT_musical_score_set_from_file() /* ADT_synthesizer: 6 */ ADT_synthesizer_set_from_file() /* ADT_musical_score: 3 */ ADT_musical_score_get_quantity_notes() /* ADT_musical_score: 6 */ ADT_musical_score_get_start_time_at() /* ADT_musical_score: 5 */ ADT_musical_score_get_duration_at() /* ADT_synthesizer: 5 */ ADT_synthesizer_get_modulation_at() /* addsynthlib: 1 */ tabsin_create_table() /* addsynthlib: 4 */ synthesize() /* ADT_musical_score: 2 */ ADT_musical_score_destroy() /* ADT_synthesizer: 2 */ ADT_synthesizer_destroy() /* ADT_synthesizer: 5 */ ADT_synthesizer_get_modulation_at() /* ADT_synthesizer: 3 */ ADT_synthesizer_get_quantity_harmonics() /* ADT_musical_score: 3 */ ADT_musical_score_get_quantity_notes() /* ADT_musical_score: 6 */ ADT_musical_score_get_start_time_at() /* ADT_musical_score: 5 */ ADT_musical_score_get_duration_at() /* ADT_synthesizer: 4 */ ADT_synthesizer_get_harmonic_at() /* ADT_musical_score: 8 */ ADT_musical_score_get_frequency_at() /* addsynthlib: 3 */ evenlope() /* ADT_synthesizer: 5 */ ADT_synthesizer_get_modulation_at() /* addsynthlib: 2 */ tabsin_destroy_table() /* ADT_musical_score: 5 */ ADT_musical_score_get_duration_at() /* ADT_musical_score: 2 */ ADT_musical_score_destroy() /* ADT_synthesizer: 2 */ ADT_synthesizer_destroy() /* ADT_wav_file: 1 */ ADT_wav_file_create_from_vector() /* ADT_wav_file: 3 */ ADT_wav_file_write() /* ADT_wav_file: 2 */ ADT_wav_file_destroy() /* ADT_wav_file: <interna> */ _write_little_endian() /* modulationlib */ modulation_constant() /* modulationlib */ modulation_quartsin() /* modulationlib */ modulation_linear() /* modulationlib */ modulation_halfcos() /* modulationlib */ modulation_invlinear() /* modulationlib */ modulation_halfsin() /* modulationlib */ modulation_sin() /* modulationlib */ modulation_log() /* modulationlib */ modulation_exp() /* modulationlib */ modulation_invlog() /* modulationlib */ modulation_invexp() /* modulationlib */ modulation_tri() /* modulationlib */ modulation_quartcos() /* modulationlib */ modulation_pulses() 11 3 Consideraciones y Estrategias 3. Consideraciones y Estrategias Durante el desarrollo se optó por una eficiente modulación mediante el uso de Tipos de Dato Abstracto. Esto permitió una simplificación del código del módulo principal (main), como también la posibilidad de aislar los módulos entre sı́, facilitando la división de tareas entre los desarrolladores. Para facilitar esta división de tareas y abordar el desarrollo, se tomó la estrategia de diseño Top-down, por lo que el problema principal se redujo en tres grandes bloques descriptos a continuación. 3.1. Validación de datos y lectura de archivos de entrada Para la lectura de los archivos de entrada se diseñaron dos TDAs especı́ficos, uno destinado al archivo de partitura y otro al de sintetizador. De esta manera, el bloque principal nunca interactúa directamente con los datos de entrada (de estos archivos, sı́ lo hace con los argumentos en la lı́nea de órdenes). Como consecuencia, el módulo principal dispone de la información previamente validada, a través de la claridad de las interfaces (getters y setters) de los TDAs. 3.2. Sı́ntesis del sonido Para generar el audio se utilizó una biblioteca de sı́ntesis aditiva, con rutinas que permiten sintetizar la partitura de manera completa, haciendo uso de los Tipos de Dato descriptos anteriormente. Aquı́ fue necesario desarrollar una función que controle la envolvente de la señal, para luego ser invocada por otra que realice la sı́ntesis final, haciendo una correcta adición de armónicos en cada nota de la partitura. Además, en esta biblioteca se incluyen rutinas para hacer un “cacheo” de la función seno de la biblioteca math, con el fin de aumentar la eficiencia de la sı́ntesis. (Esto será explicado en detalle en la sección 5.1). 3.3. Escritura en del archivo de salida en formato WAV En cuanto al archivo de salida, de formato WAV monofónico, se diseñó un tercer TDA para su manejo. Éste permite la posibilidad de crear una instancia a partir de un vector de muestras en formato double, encargándose de la normalización del audio, para su correcta representación en 16 bits. En este TDA se incluyen además rutinas para la correcta escritura del archivo, cuyos enteros tienen formato little endian. Para esto se utiliza una función interna que es capaz de escribir en 16 o 32 bits, little endian, independientemente del endianness de la plataforma. Ası́ es posible olvidarse del problema del formato de salida y manejar la sı́ntesis en un vector de double, asegurándose que la amplitud ‘nunca’ superará el rango máximo de representación del tipo. Luego el audio será normalizado, aprovechando todo este rango, sin problemas de saturación u overflow. 12 4 Resultados de ejecución Para futuras utilizaciones en otros proyectos, se listó un conjunto de primitivas realmente necesarias y útiles, que quedaron sin implementar, por lo que este TDA es el más incompleto de los tres. 4. 4.1. Resultados de ejecución En condiciones inesperadas de entrada Errores en los CLAs: Archivos de entrada inexistentes: 13 4.1 En condiciones inesperadas de entrada Archivos de entrada corruptos: 1. Incongruente cantidad de armónicos con los especificados luego en el archivo de sintetizador: 2. Funciones de modulación inexistentes o faltantes en el archivo de sintetizador: 14 4.2 En condiciones normales de entrada 3. Notas musicales inexistentes en el archivo de partitura (se considerarán como C1, do de la primera octava): 4.2. En condiciones normales de entrada Canción realizada para la prueba (disponible en el directorio ‘test’ de la entrega digital): 15 4.2 En condiciones normales de entrada Diferentes tipos de modulación sobre una misma nota musical: LINEAR 0.5; CONSTANT; HALFCOS 0.5 EXP 0.5; SIN 0.5 2; INVLOG 0.5 QUARTSIN 0.5; PULSES 1 0.25 0.5; INVLINEAR 0.5 HALFSIN 0.5; INVLINEAR 5; INVEXP 0.5 LOG 0.5; INVEXP 5; QUARTCOS 0.5 TRI 0.5 0.25 2; QUARTCOS 5; HALFCOS 0.5 16 5 Problemas encontrados en el desarrollo 5. 5.1. Problemas encontrados en el desarrollo Optimización del tiempo de sı́ntesis Durante el desarrollo, una vez terminado el Tipo de Dato Abstracto Archivo WAV (mono), se continuó con algunas pequeñas pruebas de sı́ntesis simple, sin consideración de la envolvente ni de los armónicos, y generando archivos un tanto extensos. Ası́ fue que se observó un elevado tiempo de sı́ntesis, teniendo en cuenta que finalmente, por cada nota serı́a necesario generar varias ondas como componentes armónicas de la sı́ntesis aditiva. Se sacó la conclusión de que este elevado tiempo se debı́a a una agresiva utilización de la función sin() de la biblioteca math (función que a su vez realiza varias iteraciones en su interior). Fue entonces que surgió la estrategia de crear una tabla (cache) con los valores del seno a utilizar. Se decidió ajustar la ‘resolución de tabulado’ en función de la frecuencia de muestreo, generando los valores correspondientes a una longitud de onda completa para una onda de 1 Hz de frecuencia. El acceso a la tabla se hace mediante una aritmética cı́clica, que permite calcular el ı́ndice a utilizar a partir de la variable independiente (en este caso, el tiempo). Esta tabla es inicializada una sola vez al comienzo de la ejecución y es utilizada en todo el proceso, luego de la sı́ntesis la misma es destruida. Junto con la idea de la tabulación del seno (y ya teniendo en cuenta la adición de armónicos), surgió a posteriori la ocurrencia de hacer una tabulación de la forma de onda completa, realizando la sı́ntesis aditiva por única vez y para todas las notas. Esto significarı́a un ahorro muy considerable en los tiempos de sı́ntesis. Pero se encontró un problema, si los múltiplos de la frecuencia fundamental (armónicos) fueran enteros esto serı́a totalmente posible. Lamentablemente no es ası́, una de las caracterı́sticas del sintetizador debe ser la de generar batidos por medio de múltiplos fraccionarios, cosa que jamás sucederá en el dominio de una sola longitud de onda de la fundamental. En consecuencia se adoptó la solución intermedia, con el tabulado del seno y la sı́ntesis aditiva a través de varios usos de la misma tabla. Otra posible solución hubiera sido calcular el tiempo de los batidos, muestrear en la tabla una onda de 1 Hz durante todo ese tiempo, y finalmente reajustar el cálculo del ı́ndice de acceso. A modo de reseña se adjuntan los tiempos sobre pruebas de sı́ntesis realizadas para un mismo archivo (igual duración): Uso exclusivo de la biblioteca math: 117 segundos Utilización de la tabla para evitar la invocación de sin(): 66 segundos Utilización de la tabla para almacenar la forma de onda: 10 segundos Puede observarse que a pesar de la inminente eficiencia de la última implementación, la finalmente elegida implica un ahorro de más del 40 % en el tiempo de sı́ntesis. 17 5.2 Funciones de modulación incorrectas 5.2. Funciones de modulación incorrectas Se encontraron errores en las funciones de modulación TRI y PULSES. A continuación se presentan las versiones de estas funciones corregidas. Función TRI: f (t) = ta1 t1 a1 −1 (t t1 −t0 t ≤ t1 − t0 ) + 1 t > t1 n o 0 1 Función PULSES: f (t0 ) = mı́n | 1−a (2t − 1)t | + a ; 1 , t0 = 0 1 t1 6. t t0 − b tt0 c Conclusiones El programa cuenta con soporte de múltiples idiomas que se definen en tiempo de compilación, mediante el uso de un archivo auxiliar incluido en el archivo Makefile. El uso de make permite realizar proyectos muy profesionales y automatizados, aumentando además las cualidades de facilidad de uso y verificabilidad, ya que la compilación se realiza mediante un simple comando en el terminal, y los módulos sin modificaciones no son compilados innecesariamente. El uso de los TDAs en este trabajo ha sido fundamental, las posibilidades de reutilización de los mismos en otras aplicaciones, la simplificación de código, como también las posibles futuras modificaciones a este programa lo hacen una herramienta fundamental en la buena programación en lenguaje C. Cualidades de modularización, mantenibilidad, evolucionabilidad, y comprensibilidad se incrementan notablemente mediante la utilización de esta técnica, que es lo más cercano a la Programación Orientada a Objetos (OOP) que se puede lograr en el lenguaje C. 7. Bibliografı́a consultada The Not So Short Introduction to LATEX 2ε (Tobias Oetiker). URL: http://tobi.oetiker.ch/lshort/lshort.pdf The Listings Package (Carsten Heinz - Brooks Moses). URL: ftp://ftp.tex.ac.uk/tex-archive/macros/latex/contrib/listings/listings.pdf Fundamentals of Software Engineering (Ghezzi-Jazayeri-Mandrioli). ISBN-13: 978-0133056990 18 8 Códigos fuente 8. Códigos fuente 8.1. ADT musical score 8.1.1. ADT musical score.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Algoritmos y Programaci ó n I - 75.02/95.11 - Curso Ing . Mart ı́ n Cardozo TP N o 3 - 1 er Cuatrimestre 2012 Alumnos : ARIAS , Francisco - FERRARI BIHURRIET , Francisco Archivo : AD T_mus ical_s core . h Descrip : Encabezado p ú blico para el TDA partitura musical . Obs : * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include " ../ main_modules / common . h " 16 17 18 19 20 #if ndef A D T_ M U SI C A L_ S C OR E _ H #define A DT _ M US I C AL _ S CO R E _H 21 22 23 24 25 26 typedef struct A DT _ m us i c al _ s co r e _t A DT _ m us i c al _ s c or e _ t ; 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 typedef struct tnote tnote ; typedef enum { C =0 , Cs =1 , D =2 , Ds =3 , E =4 , F =5 , Fs =6 , G =7 , Gs =8 , A =9 , As =10 , B =11 } tone_t ; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Primitives * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* 1) Creador de partitura */ status_t A D T _ m u s i c a l _ s c o r e _ n e w ( A D T _m u s ic a l _s c o re _ t **) ; /* 2) Destructor de partitura */ void A D T _ m u s i c a l _ s c o r e _ d e s t r o y ( A DT _ m us i c al _ s co r e _t **) ; 19 8.1 ADT musical score 49 50 51 52 53 /* 3) Obtener la cantidad de notas . Precondicion : no debe recibir NULL */ size_t A D T _ m u s i c a l _ s c o r e _ g e t _ q u a n t i t y _ n o t e s ( const A DT _ m us i c al _ s co r e _t * ) ; 4) Obtener la n - sima nota . En caso de fallar devuelve NULL . PRECONDICION : SE DEBE TENER ACCESO AL ARCHIVO 54 A D T _ m u s i c a l _ s c o r e _ P R I V A T E . h */ 55 tnote * A D T _ m u s i c a l _ s c o r e _ g e t _ n o t e _ a t ( const A D T _m u s ic a l _s c o re _ t * , size_t ) ; 56 57 58 59 /* 5) Obtener la duracion de la n - sima nota . Precondiciones : I ) No debe recibir puntero NULL II ) La posicion debe ser menor que la cant de notas */ 60 double A D T _ m u s i c a l _ s c o r e _ g e t _ d u r a t i o n _ a t ( const A DT _ m us i c al _ s co r e _t * , size_t ) ; 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 /* /* 6) Obtener el tiempo de inicio de la n - sima nota . Precondiciones : I ) No debe recibir puntero NULL II ) La posicion debe ser menor que la cant de notas */ double A D T _ m u s i c a l _ s c o r e _ g e t _ s t a r t _ t i m e _ a t ( const A DT _ m us i c al _ s co r e _t * , size_t ) ; /* 7) Obtener el tono de la n - sima nota . Precondiciones : I ) No debe recibir puntero NULL II ) La posicion debe ser menor que la cant de notas */ tone_t A D T _ m u s i c a l _ s c o r e _ g e t _ t o n e _ a t ( const A DT _ m us i c al _ s co r e _t * , size_t ) ; /* 8) Obneter la fracuencia de la n - sina nota I ) No debe recibir puntero NULL II ) La posicion debe ser menor que la cant de notas */ double A D T _ m u s i c a l _ s c o r e _ g e t _ f r e q u e n c y _ a t ( const A DT _ m us i c al _ s co r e _t * , size_t ) ; 77 78 79 80 81 82 /* 9) Leer notas desde archivo */ status_t A D T _ m u s i c a l _ s c o r e _ s e t _ f r o m _ f i l e ( A D T _m u s ic a l _s c o re _ t ** , string ) ; 83 84 85 86 87 88 /* 11) Escribir la nota n - esima ( TODO ) status_t A D T _ m u s i c a l _ s c o r e _ s e t _ e l e m e n t _ a t ( A D T _m u s ic a l _s c o re _ t * , void * , long ) ; */ 89 90 /* 10) Imprimir partitura */ status_t A D T _ m u s i c a l _ s c o r e _ p r i n t ( const A D T _m u s ic a l _s c o re _ t *) ; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #endif /* A DT _ M US I C AL _ S CO R E _H */ 8.1.2. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ADT musical score PRIVATE.h /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Algoritmos y Programaci ó n I - 75.02/95.11 - Curso Ing . Mart ı́ n Cardozo TP N o 3 - 1 er Cuatrimestre 2012 Alumnos : Archivo : Descrip : Obs : ARIAS , Francisco - FERRARI BIHURRIET , Francisco ADT_musical_score_PRIVATE .h Encabezado privado para el TDA partitura musical . Para una correcta utilizaci ó n del TDA no debe conocerse el funcionamiento interno , el cu á l queda expuesto aqu ı́ . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include " ADT_ musica l_scor e . h " 20 8.1 ADT musical score 16 17 18 19 20 #if ndef A D T _ M U S I C A L _ S C O R E _ P R I V A T E _ H #define A D T _ M U S I C A L _ S C O R E _ P R I V A T E _ H #define #define #define #define #define #define #define 27 #define 28 #define 21 22 23 24 25 26 29 30 31 32 const string string_tones [ QUANTITY_TONES ]= { "C", " Cs " , "D", " Ds " , "E", "F", " Fs " , "G", " Gs " , "A", " As " , "B" 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 73 74 /* Db */ /* Eb */ /* Gb */ /* Ab */ /* Bb */ }; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* . . . . . . . . . . . . . . . . . . . . . . Manejo de memoria dinamica . . . . . . . . . . . . . . . . . . . . . . */ #define INIT_CHOP 10 #define CHOP_SIZE 10 /* memoria inicial */ /* incremento de memoria */ /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /* . . . . . . . . . . . . . . . . . . . . . . . Estructura del ADT partitura . .. . . .. . . .. . . .. . . .. */ struct tnote { 61 62 63 64 65 66 67 68 69 70 71 72 N 0 /* 0 or 1 */ SCALE_FACTOR 1 .0 5 9 46 3 0 94 3 5 92 9 5 26 /* ( pow (2 ,1.0/ QUANTITY_TONES ) ) */ SIZE_AUX_VEC 30 STRING_SPACE " " /* separador de parametros en partitura */ QUANTITY_TONES 12 /* cantidad de tonos en una octava musical */ C1_FREQUENCY 1 6. 3 5 15 9 7 83 1 2 87 4 1 47 BEMOL_SYMBOL ' b ' SHARP_SYMBOL ' s ' EMPTY_LINE " \ n " double double tone_t uchar start_time ; duration ; tone ; octave ; }; struct A DT _ m us i c al _ s co r e _t { tnote ** notes ; size_t quantity_notes ; size_t alloc_size ; 21 8.1 ADT musical score 75 76 77 78 79 80 }; /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ #endif /* A D T _ M U S I C A L _ S C O R E _ P R I V A T E _ H */ 8.1.3. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ADT musical score.c /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Algoritmos y Programaci ó n I - 75.02/95.11 - Curso Ing . Mart ı́ n Cardozo TP N o 3 - 1 er Cuatrimestre 2012 Alumnos : Archivo : Descrip : Obs : * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include 20 #include 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 ARIAS , Francisco - FERRARI BIHURRIET , Francisco AD T_mus ical_s core . c Implementaci ó n del TDA partitura musical . Compilacion en modo prueba : gcc A DT_mus ical_s core . c -o musical_score - ansi - pedantic - Wall - lm - DTEST < stdio .h > < stdlib .h > < string .h > < math .h > " ADT_musical_score_PRIVATE .h" /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 1) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / | Creador de partitura | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ status_t A D T _ m u s i c a l _ s c o r e _ n e w ( A D T _m u s ic a l _s c o re _ t ** musical_score ) { size_t i , j ; if ( musical_score == NULL ) return ERR OR _N UL L_ PO IN TE R ; if ( ((* musical_score ) = ( A DT _ m us i c al _ s co r e _t *) malloc ( sizeof ( A DT _ m us i c al _ s co r e _t ) ) ) == NULL ) return ERROR_NO_MEMORY ; if ( ((* musical_score ) -> notes = ( tnote **) malloc ( INIT_CHOP * sizeof ( tnote *) ) ) == NULL ) { free ( * musical_score ) ; * musical_score = NULL ; return ERROR_NO_MEMORY ; } for ( i =0; i < INIT_CHOP ; i ++) { if ( ((* musical_score ) -> notes [ i ] = ( tnote *) malloc ( sizeof ( tnote ) ) ) == NULL ) { for ( j =0; j < i ; j ++) free ((* musical_score ) -> notes [ j ]) ; free ((* musical_score ) -> notes ) ; free (* musical_score ) ; 22 8.1 ADT musical score * musical_score = NULL ; return ERROR_NO_MEMORY ; 52 53 54 55 56 } } 57 58 59 60 61 62 (* musical_score ) -> quantity_notes = 0; (* musical_score ) -> alloc_size = INIT_CHOP ; return OK ; 63 64 65 66 67 68 } 69 70 71 72 73 void A D T _ m u s i c a l _ s c o r e _ d e s t r o y ( A DT _ m us i c al _ s co r e _t ** musical_score ) { /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 2) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / | Destructor de partitura | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ size_t i , aux_alloc_size ; aux_alloc_size = (* musical_score ) -> alloc_size ; 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 for ( i =0; i < aux_alloc_size ; i ++) free (((* musical_score ) -> notes [ i ]) ) ; free ((* musical_score ) -> notes ) ; free (* musical_score ) ; * musical_score = NULL ; } /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 3) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / | Obtener la cantidad de notas | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ size_t A D T _ m u s i c a l _ s c o r e _ g e t _ q u a n t i t y _ n o t e s ( const A DT _ m us i c al _ s co r e _t * musical_score ) { return musical_score - > quantity_notes ; } /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 4) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / | Obtener la n - sima nota | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ tnote * A D T _ m u s i c a l _ s c o r e _ g e t _ n o t e _ a t ( const A D T _m u s ic a l _s c o re _ t * musical_score , size_t position ) { if ( musical_score == NULL || ( musical_score - > quantity_notes ) < position ) return NULL ; return musical_score - > notes [ position - N ]; } /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 5) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / | Obtener la duracion de la n - sima nota |\ \\\\\\ \\\\\\ \\| */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ double A D T _ m u s i c a l _ s c o r e _ g e t _ d u r a t i o n _ a t ( const A DT _ m us i c al _ s co r e _t * 23 8.1 ADT musical score 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 musical_score , size_t position ) { return ( musical_score - > notes [ position - N ]) -> duration ; } /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 6) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* |////////////| Obtener el tiempo de inicio de la n - sima nota |\\\\\\\\\\\\\| */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ double A D T _ m u s i c a l _ s c o r e _ g e t _ s t a r t _ t i m e _ a t ( const A DT _ m us i c al _ s co r e _t * musical_score , size_t position ) { return ( musical_score - > notes [ position - N ]) -> start_time ; } /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 7) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / | Obtener el tono de la n - sima nota | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ 128 /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 tone_t A D T _ m u s i c a l _ s c o r e _ g e t _ t o n e _ a t ( const A DT _ m us i c al _ s co r e _t * musical_score , size_t position ) { return ( musical_score - > notes [ position - N ]) -> tone ; } /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 8) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* |//////////////| Obneter la fracuencia de la n - sina nota | \\ \ \ \\ \ \ \\ \ \ \\ \ \ \| */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ double A D T _ m u s i c a l _ s c o r e _ g e t _ f r e q u e n c y _ a t ( const A DT _ m us i c al _ s co r e _t * musical_score , size_t position ) { return C1_FREQUENCY * pow (2 ,(( musical_score - > notes [ position - N ] - > octave ) -1) ) * pow ( SCALE_FACTOR , ( musical_score - > notes [ position - N ] - > tone ) ) ; } /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 9) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / | Leer notas desde archivo | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ status_t A D T _ m u s i c a l _ s c o r e _ s e t _ f r o m _ f i l e ( A D T _m u s ic a l _ sc o r e_ t ** musical_score , string f i l e _ n a m e _ m u s i c a l _ s c o r e ) { FILE * f il e_ mu si ca l_ sc or e ; size_t i ; size_t aux_alloc_size = INIT_CHOP ; size_t aux _q ua nt it y_ no te s = 0; tnote ** aux_notes ; char aux_vec [ SIZE_AUX_VEC ]; string aux_string ; if ( musical_score == NULL || f i l e _ n a m e _ m u s i c a l _ s c o r e == NULL ) return E RR OR _N UL L_ PO IN TE R ; if ( ( f il e_ mu si ca l_ sc or e = fopen ( file_name_musical_score , " r " ) ) == NULL ) { A D T _ m u s i c a l _ s c o r e _ d e s t r o y ( musical_score ) ; return E RR O R _M U S IC A L _S C O RE ; 24 8.1 ADT musical score 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 } while ( fgets ( aux_vec , SIZE_AUX_VEC , fi le _m us ic al _s co re ) != NULL ) { if ( ! strcmp ( aux_vec , EMPTY_LINE ) ) { A D T _ m u s i c a l _ s c o r e _ d e s t r o y ( musical_score ) ; return E RR O R _M U S IC A L _S C O RE ; } if ( a ux _q ua nt it y_ no te s == aux_alloc_size ) { if ( ( aux_notes = ( tnote **) realloc ((* musical_score ) -> notes , sizeof ( tnote *) *( aux_alloc_size + CHOP_SIZE ) ) ) == NULL ) { A D T _ m u s i c a l _ s c o r e _ d e s t r o y ( musical_score ) ; return ERROR_NO_MEMORY ; } 187 188 189 190 191 (* musical_score ) -> notes = aux_notes ; for ( i = aux_alloc_size ; i <( aux_alloc_size + CHOP_SIZE ) ; i ++) { if ( ((* musical_score ) -> notes [ i ] = malloc ( sizeof ( tnote ) ) ) == NULL ) { (* musical_score ) -> alloc_size = ( aux_alloc_size + i ) ; A D T _ m u s i c a l _ s c o r e _ d e s t r o y ( musical_score ) ; return ERROR_NO_MEMORY ; 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 } } aux_alloc_size += CHOP_SIZE ; } aux_string = strtok ( aux_vec , STRING_SPACE ) ; (* musical_score ) -> notes [ aux _q ua nt it y_ no te s ] - > start_time = strtod ( aux_string , NULL ) ; aux_string = strtok ( NULL , STRING_SPACE ) ; for ( i =0; i < QUANTITY_TONES ; i ++) { if ( ! strncmp ( aux_string , string_tones [ i ] ,1) ) { if ( aux_string [1] == BEMOL_SYMBOL ) { (* musical_score ) -> notes [ au x_q ua nt it y_ no te s ] - > tone = ( tone_t ) (i -1) ; (* musical_score ) -> notes [ au x_q ua nt it y_ no te s ] - > octave = ( uchar ) strtoul ( aux_string +2 , NULL ,0) ; break ; } if ( aux_string [1] == SHARP_SYMBOL ) { (* musical_score ) -> notes [ au x_q ua nt it y_ no te s ] - > tone = ( tone_t ) ( i +1) ; (* musical_score ) -> notes [ au x_q ua nt it y_ no te s ] - > octave = ( uchar ) strtoul ( aux_string +2 , NULL ,0) ; break ; } 25 8.1 ADT musical score 229 230 231 232 233 (* musical_score ) -> notes [ a ux _q ua nt it y_ no te s ] - > tone = ( tone_t ) i ; (* musical_score ) -> notes [ a ux _q ua nt it y_ no te s ] - > octave = ( uchar ) strtoul ( aux_string +1 , NULL ,0) ; break ; 234 235 236 237 238 239 } } aux_string = strtok ( NULL , STRING_SPACE ) ; (* musical_score ) -> notes [ aux _q ua nt it y_ no te s ] - > duration = strtod ( aux_string , NULL ) ; 240 241 242 243 244 245 au x_ qu an ti ty _n ot es ++; } 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 (* musical_score ) -> quantity_notes = aux _q ua nt it y_ no te s ; (* musical_score ) -> alloc_size = aux_alloc_size ; fclose ( fil e_ mu si ca l_ sc or e ) ; return OK ; } /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 10) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / | Imprimir partitura | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ status_t A D T _ m u s i c a l _ s c o r e _ p r i n t ( const A D T _m u s ic a l _s c o r e_ t * musical_score ) { 263 264 265 266 267 268 size_t i , quantity_notes ; if ( musical_score == NULL ) return ERR OR _N UL L_ PO IN TE R ; quantity_notes = A D T _ m u s i c a l _ s c o r e _ g e t _ q u a n t i t y _ n o t e s ( musical_score ) ; 269 270 271 272 273 for ( i =0; i < quantity_notes ; i ++) printf ( " %f %s %u %f frequency --> %f \ n " , A D T _ m u s i c a l _ s c o r e _ g e t _ s t a r t _ t i m e _ a t ( musical_score , i ) , string_tones [ musical_score - > notes [ i ] - > tone ] , ( uint ) musical_score - > notes [ i ] - > octave , A D T _ m u s i c a l _ s c o r e _ g e t _ d u r a t i o n _ a t ( musical_score , i ) , A D T _ m u s i c a l _ s c o r e _ g e t _ f r e q u e n c y _ a t ( musical_score , i ) ) ; 274 275 276 277 278 279 280 281 282 283 284 285 286 287 return OK ; } /* | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | */ /* | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | MAIN de prueba | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | */ /* | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | */ 26 8.2 ADT synthesizer 288 289 290 291 292 293 294 295 296 297 298 #if def TEST int main ( void ) { ADT _ m us i c a l_ s c or e _ t * musical_score ; /* Creacion (1) */ if ( ( A D T _ m u s i c a l _ s c o r e _ n e w (& musical_score ) ) != OK ) { fprintf ( stderr , " Error en la creacion de la partitura \ n " ) ; return EXIT_FAILURE ; } 299 300 301 302 303 304 /* Llenado (9) */ if ( ( A D T _ m u s i c a l _ s c o r e _ s e t _ f r o m _ f i l e (& musical_score , " TEST_PARTITURA . txt " ) ) != OK ) { fprintf ( stderr , " Error en el seteo de los elementos \ n " ) ; return EXIT_FAILURE ; } 305 306 307 308 309 /* Impresion (10) */ if ( ( A D T _ m u s i c a l _ s c o r e _ p r i n t ( musical_score ) ) != OK ) { fprintf ( stderr , " Error en la impresion de prueba \ n " ) ; return EXIT_FAILURE ; } 310 311 312 313 314 315 /* Destruccion (2) */ 316 317 318 319 320 321 } 322 323 #endif A D T _ m u s i c a l _ s c o r e _ d e s t r o y (& musical_score ) ; return EXIT_SUCCESS ; ADT synthesizer 8.2. 8.2.1. 1 2 3 4 5 6 7 8 9 10 11 12 modulationlib.h /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Algoritmos y Programaci ó n I - 75.02/95.11 - Curso Ing . Mart ı́ n Cardozo TP N o 3 - 1 er Cuatrimestre 2012 Alumnos : Archivo : Descrip : Obs : 1) 2) ARIAS , Francisco - FERRARI BIHURRIET , Francisco modulationlib . h Encabezado de la biblioteca modulationlib . Precondiciones : El puntero recibido no debe ser NULL . El primer elemento del vector ( t0 ) debe ser distinto de cero . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 13 14 15 16 17 #if ndef MODULATIONLIB_H #define MODULATIONLIB_H 18 19 #define PI 3 . 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 2 3 8 4 6 27 8.2 ADT synthesizer 20 21 22 23 24 /* Posici ó n de los par á metros en el vector */ #define param_T0 0 #define param_T1 1 #define param_A1 2 25 #define param_A 0 26 #define param_F 1 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 /* * * * * * * * * * * * * * * * * * * * * * * * PROTOTYPES * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ double double double double double double double double double double double double double double /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #endif /* MODULATIONLIB_H */ 8.2.2. 1 2 15 16 17 18 19 20 21 22 23 24 25 26 27 28 modulationlib.c /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Algoritmos y Programaci ó n I - 75.02/95.11 - Curso Ing . Mart ı́ n Cardozo TP N o 3 - 1 er Cuatrimestre 2012 3 4 5 6 7 8 9 10 11 12 13 14 mo d u la t i on _ c o ns t a nt ( const double [] , double ) ; mod ulatio n_line ar ( const double [] , double ) ; m o d u l a t i o n _ i n v l i n e a r ( const double [] , double ) ; modulation_sin ( const double [] , double ) ; modulation_exp ( const double [] , double ) ; mod ulatio n_inve xp ( const double [] , double ) ; mo d u la t i on _ q u ar t c os ( const double [] , double ) ; mo d u la t i on _ q u ar t s in ( const double [] , double ) ; m od ul at io n_ ha lf co s ( const double [] , double ) ; m od ul at io n_ ha lf si n ( const double [] , double ) ; modulation_log ( const double [] , double ) ; mod ulatio n_invl og ( const double [] , double ) ; modulation_tri ( const double [] , double ) ; mod ulatio n_puls es ( const double [] , double ) ; Alumnos : ARIAS , Francisco - FERRARI BIHURRIET , Francisco Archivo : modulationlib . c Descrip : Biblioteca de moduladores de la amplitud en la se ~ n al de audio . Obs : * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include < math .h > < stdio .h > < stdlib .h > " modulationlib . h " /* Macro de funci ó n : m ı́ nimo entre dos valores */ #define MINIMUM (a , b ) (( a ) <( b ) ?( a ) :( b ) ) /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Par á metros en el vector , estas macros son poco expl ı́ citas y cortas , para acortar las f ó rmulas en las funciones , por eso se declaran dentro de ' modulationlib . c ' , para que sean internas y no entren en en conflicto con otras definiciones . 28 8.2 ADT synthesizer */ #define #define #define #define 34 #define 29 30 31 32 33 T0 T1 A1 A F parameters [ param_T0 ] parameters [ param_T1 ] parameters [ param_A1 ] parameters [ param_A ] parameters [ param_F ] 35 36 37 38 39 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* CONSTANT */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ double mo d u la t i on _ c on s t a nt ( const double parameters [] , double t ) 40 { 41 return 1; 42 } 43 44 45 46 47 48 49 50 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* LINEAR */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ double mo dulati on_lin ear ( const double parameters [] , double t ) { return t / T0 ; } 51 52 53 54 55 56 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* INVLINEAR */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ double m o d u l a t i o n _ i n v l i n e a r ( const double parameters [] , double t ) { 57 if ( T0 < t ) return 0; /* 0 > 1 - t / T0 */ 58 return 1 - t / T0 ; 59 } 60 61 62 63 64 65 66 67 68 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* SIN */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ double modulation_sin ( const double parameters [] , double t ) { return 1 + A * sin (2* PI * F * t ) ; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* EXP */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ double modulation_exp ( const double parameters [] , double t ) { 74 return exp (( -5*( T0 - t ) ) / T0 ) ; 75 } 69 70 71 72 73 76 77 78 79 80 81 82 83 84 85 86 87 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* INVEXP */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ double mo dulati on_inv exp ( const double parameters [] , double t ) { return exp (( -5* t ) / T0 ) ; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* QUARTCOS */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 29 8.2 ADT synthesizer 88 89 90 91 92 double mo d u la t i o n_ q u ar t c os ( const double parameters [] , double t ) { return cos (( PI * t ) /(2* T0 ) ) ; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* QUARTSIN */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ double mo d u la t i on _ q u ar t s in ( const double parameters [] , double t ) { return sin (( PI * t ) /(2* T0 ) ) ; 99 } 93 94 95 96 97 98 100 101 102 103 104 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* HALFCOS */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ double m od ul at io n_ ha lf co s ( const double parameters [] , double t ) 105 { 106 return (1+ cos (( PI * t ) / T0 ) ) /2; 107 } 108 109 110 111 112 113 114 115 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* HALFSIN */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ double m od ul at io n_ ha lf si n ( const double parameters [] , double t ) { return (1+ sin ( PI *(( t - T0 ) / T0 +0.5) ) ) /2; } 116 117 118 119 120 121 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* LOG */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ double modulation_log ( const double parameters [] , double t ) { 122 return log10 ((9* t ) / T0 + 1) ; 123 } 124 125 126 127 128 129 130 131 132 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* INVLOG */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ double mod ulatio n_invl og ( const double parameters [] , double t ) { if ( t < T0 ) return log10 (( -9* t ) / T0 + 10) ; return 0; } 133 134 135 136 137 138 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* TRI */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ double modulation_tri ( const double parameters [] , double t ) { 139 if ( t <= T1 ) return ( t * A1 ) / T1 ; 140 return (t - T0 ) *( A1 -1) /( T1 - T0 ) + 1; 141 } 142 143 144 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* PULSES */ 145 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 146 double mod ulatio n_puls es ( const double parameters [] , double t ) 30 8.2 ADT synthesizer 147 148 149 150 151 152 153 { double aux ; t = t / T0 - floor ( t / T0 ) ; /* t ' */ aux = fabs ( ((1 - A1 ) / T1 ) * (2* t -1) * T0 ) + A1 ; return MINIMUM ( aux ,1) ; } 8.2.3. 1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 Algoritmos y Programaci ó n I - 75.02/95.11 - Curso Ing . Mart ı́ n Cardozo TP N o 3 - 1 er Cuatrimestre 2012 Alumnos : ARIAS , Francisco - FERRARI BIHURRIET , Francisco Archivo : ADT_synthesizer . h Descrip : Encabezado p ú blico para el TDA sintetizador . Obs : * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include " A D T _ s y n t h e s i z e r _ P R I V A T E . h " #include " ../ main_modules / common . h " #include " modulationlib . h " #if ndef A DT_SYN THESI ZER_H #define A DT_SYN THESIZ ER_H static const modulation_t m o d u l a t i o n _ f u n c t i o n s [ Q UA N T IT Y _ MO D U LA T O RS ] = { modulation_constant , modulation_linear , modulation_invlinear , modulation_sin , modulation_exp , modulation_invexp , modulation_quartcos , modulation_quartsin , modulation_halfcos , modulation_halfsin , modulation_log , modulation_invlog , modulation_tri , modu lation _pulse s 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 ADT synthesizer.h }; static const string st ring_m odulat ors [ Q UA N T IT Y _ MO D U LA T O RS ] = { " CONSTANT " , " LINEAR " , " INVLINEAR " , " SIN " , " EXP " , " INVEXP " , " QUARTCOS " , " QUARTSIN " , " HALFCOS " , 31 8.2 ADT synthesizer " HALFSIN " , " LOG " , " INVLOG " , " TRI " , " PULSES " 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 }; typedef enum { ATTACK =0 , SUSTAINED =1 , RELEASE =2} t ype_mo dulati on_t ; typedef struct A DT_syn thesiz er_t A DT_syn thesiz er_t ; typedef struct tharmonic tharmonic ; typedef struct tmodulation tmodulation ; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * primitives * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* 1) Creador de sintetizador */ status_t A D T _s y n th e s iz e r _n e w ( ADT_ synthe sizer_ t **) ; /* 2) Destructor de sintetizador */ void A D T _ s y n t h e s i z e r _ d e s t r o y ( AD T_synt hesize r_t **) ; 3) Obtener la cantidad de armonicos . Precondicion : no debe recibir puntero NULL */ 79 size_t A D T _ s y n t h e s i z e r _ g e t _ q u a n t i t y _ h a r m o n i c s ( const AD T_syn thesiz er_t *) ; 80 81 82 83 84 /* 4) Obtener el n - sima armonico . La funcion devuelve por el penultimo argumento los pares de multiplo y por el ultimo arguemento la intesidad */ status_t A D T _ s y n t h e s i z e r _ g e t _ h a r m o n i c _ a t ( const ADT_ synthe sizer_ t * , size_t , 85 double * , double *) ; 86 87 88 89 90 /* 5) Obtener la modulacion . El segundo argumento funciona como una bandera indicadora de la modulacion deseada ( ATTACK , SUSTAINED o RELEASE ) . la funcion devuelve por interfaz la modularizacion deseada y los parametros relacionados con dicha modulacion */ 91 status_t A D T _ s y n t h e s i z e r _ g e t _ m o d u l a t i o n _ a t ( const ADT_ synthe sizer_ t * , 92 type_modulation_t , double ** , 93 modulation_t *) ; 94 95 /* /* 6) Escribir desde archivo */ status_t A D T _ s y n t h e s i z e r _ s e t _ f r o m _ f i l e ( ADT_ synthe sizer_ t ** , string ) ; 96 97 98 99 100 101 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 102 103 104 #endif /* AD T_SYNT HESIZE R_H */ /* 7) Imprimir copia del archivo sitetizador */ status_t A D T _ s y n t h e s i z e r _ p r i n t ( const ADT_ synthe sizer_ t *) ; 8.2.4. 1 2 3 ADT synthesizer PRIVATE.h /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Algoritmos y Programaci ó n I - 75.02/95.11 - Curso Ing . Mart ı́ n Cardozo 32 8.2 ADT synthesizer TP N o 3 - 1 er Cuatrimestre 2012 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 Alumnos : Archivo : Descrip : Obs : * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include " modulationlib . h " #if ndef A D T _ S Y N T H E S I Z E R _ P R I V A T E _ H #define A D T _ S Y N T H E S I Z E R _ P R I V A T E _ H /* *************** Declaration of a function pointer types * * * * * * * * * * * * * * * * * * * * */ typedef double (* modulation_t ) ( const double [] , double ) ; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #define #define #define #define 32 #define 33 #define 34 #define 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 ARIAS , Francisco - FERRARI BIHURRIET , Francisco ADT_synthesizer_PRIVATE .h Encabezado privado para el TDA sintetizador . Para una correcta utilizaci ó n del TDA no debe conocerse el funcionamiento interno , el cu á l queda expuesto aqu ı́ . N 0 Q UA N T IT Y _ PA R A ME T E RS 3 SIZE_AUX_VEC 30 STRING_SPACE " " Q UA N T IT Y _ MO D U LA T O RS 14 PHASE_MODULATION_AMOUNT 3 FILE_NAME_TEST " T EST_SI NTETIZ ADOR . txt " /* . . . . . . . . . . . . . . . . . . . . . . . Estructura del ADT sintetizador . .. . . .. . . .. . . .. .. .. */ struct tharmonic { double multiples_pairs ; double intensity ; }; struct tmodulation { modulation_t modulation ; double parameters [ Q UA N T IT Y _ PA R A ME T E RS ]; }; struct AD T_synt hesize r_t { unsigned char quan tity_h armoni c ; struct tharmonic ** harmonics ; struct tmodulation ** modulators ; /* 0: Attack - 1: Sustained - 2: Release */ }; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #endif /* A D T _ S Y N T H E S I Z E R _ P R I V A T E _ H */ 33 8.2 ADT synthesizer 8.2.5. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 ADT synthesizer.c /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Algoritmos y Programaci ó n I - 75.02/95.11 - Curso Ing . Mart ı́ n Cardozo TP N o 3 - 1 er Cuatrimestre 2012 Alumnos : Archivo : Descrip : Obs : ARIAS , Francisco - FERRARI BIHURRIET , Francisco ADT_synthesizer . c Implementaci ó n del TDA sintetizador . Compilacion en modo prueba : gcc ADT_synthesizer . c modulationlib . c -o synthesizer - ansi - pedantic - Wall - lm - DTEST * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #include #include #include #include #include < stdio .h > < stdlib .h > < string .h > < math .h > < ctype .h > " ../ main_modules / common . h " " ADT_synthesizer_PRIVATE .h" " ADT_synthesizer . h " " modulationlib . h " /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 1) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / | Creador de sintetizador | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ status_t A D T _s y n th e s iz e r _n e w ( ADT_ synthe sizer_ t ** synthesizer ) { size_t i , j ; 36 37 38 39 40 41 if ( synthesizer == NULL ) return ERR OR _N UL L_ PO IN TE R ; 42 43 44 45 46 47 if ( ((* synthesizer ) -> modulators = ( tmodulation **) malloc ( P H A S E _ M O D U L A T I O N _ A M O U N T * sizeof ( tmodulation *) ) ) == NULL ) { free (* synthesizer ) ; * synthesizer = NULL ; return ERROR_NO_MEMORY ; } 48 49 50 51 52 53 54 55 56 57 if ( ((* synthesizer ) = ( AD T_synt hesize r_t *) malloc ( sizeof ( AD T_synt hesize r_t ) ) ) == NULL ) return ERROR_NO_MEMORY ; for ( i =0; i < P H A S E _ M O D U L A T I O N _ A M O U N T ; i ++) { if ( ((* synthesizer ) -> modulators [ i ] = ( tmodulation *) malloc ( sizeof ( tmodulation ) ) ) == NULL ) { for ( j =0; j < i ; j ++) free ((* synthesizer ) -> modulators [ j ]) ; free ((* synthesizer ) -> modulators ) ; free (* synthesizer ) ; * synthesizer = NULL ; return ERROR_NO_MEMORY ; 34 8.2 ADT synthesizer } 58 59 60 61 62 } (* synthesizer ) -> qu antity _harmo nic = 0; (* synthesizer ) -> harmonics = NULL ; 63 64 65 66 67 68 69 70 71 72 73 74 for ( j =0; j < P H A S E _ M O D U L A T I O N _ A M O U N T ; j ++) { (* synthesizer ) -> modulators [ j ] - > modulation = NULL ; for ( i =0; i < Q U AN T I TY _ P AR A M ET E R S ; i ++) (* synthesizer ) -> modulators [ j ] - > parameters [ i ] = 0; } return OK ; } 75 76 77 78 79 /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 2) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / | Destructor de sintetizador | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ 80 81 82 83 84 85 void A D T _ s y n t h e s i z e r _ d e s t r o y ( AD T_synt hesize r_t ** synthesizer ) { size_t i , a u x _ q u a n t i t y _ h a r m o n i c ; a u x _ q u a n t i t y _ h a r m o n i c = (* synthesizer ) -> qua ntity_ harmon ic ; for ( i =0; i < a u x _ q u a n t i t y _ h a r m o n i c ; i ++) free ((* synthesizer ) -> harmonics [ i ]) ; free ((* synthesizer ) -> harmonics ) ; for ( i =0; i < P H A S E _ M O D U L A T I O N _ A M O U N T ; i ++) free ((* synthesizer ) -> modulators [ i ]) ; free ((* synthesizer ) -> modulators ) ; free (* synthesizer ) ; * synthesizer = NULL ; 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 } /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 3) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / | Obtener la cantidad de armonicos | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ size_t A D T _ s y n t h e s i z e r _ g e t _ q u a n t i t y _ h a r m o n i c s ( const AD T_synt hesiz er_t * synthesizer ) { return synthesizer - > qu antity _harmo nic ; } /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 4) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / | Obtener el n - sima armonico | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ 109 /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ 110 111 112 113 114 115 116 status_t A D T _ s y n t h e s i z e r _ g e t _ h a r m o n i c _ a t ( const ADT_ synthe sizer_ t * synthesizer , size_t position , double * multiples_pairs , double * intensity ) { if ( synthesizer == NULL || synthesizer - > qu antity _harmo nic < position ) return E RR OR _N UL L_ PO IN TE R ; 35 8.2 ADT synthesizer 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 * multiples_pairs = ( synthesizer - > harmonics [ position - N ] - > multiples_pairs ) ; * intensity = ( synthesizer - > harmonics [ position - N ] - > intensity ) ; return OK ; } /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 5) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / | Obtener la modulacion . | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ status_t A D T _ s y n t h e s i z e r _ g e t _ m o d u l a t i o n _ a t ( const ADT_ synthe sizer_ t * synthesizer , type _modul ation_ t modulation , double ** parameters , modulation_t * modulator ) { size_t i ; if ( synthesizer == NULL ) return ERR OR _N UL L_ PO IN TE R ; for ( i =0; i < P H A S E _ M O D U L A T I O N _ A M O U N T ; i ++) { if ( modulation == i ) { if ( modulator == NULL ) { * parameters = ( synthesizer - > modulators [ i ] - > parameters ) ; return OK ; } * parameters = ( synthesizer - > modulators [ i ] - > parameters ) ; * modulator = ( synthesizer - > modulators [ i ] - > modulation ) ; } } 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 return OK ; } /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 6) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / | Escribir desde archivo | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ status_t A D T _ s y n t h e s i z e r _ s e t _ f r o m _ f i l e ( ADT_ synthe sizer_ t ** synthesizer , string f i l e _ n a m e _ s y n t h e s i z e r ) { size_t i ,j ,L , a u x _ q u a n t i t y _ h a r m o n i c ; FILE * file_synthesizer ; char aux_vec [ SIZE_AUX_VEC ]; string aux_string ; if ( synthesizer == NULL || f i l e _ n a m e _ s y n t h e s i z e r == NULL ) return E RR OR _N UL L_ PO IN TE R ; if ( ( file_synthesizer = fopen ( file_name_synthesizer , " r " ) ) == NULL ) { A D T _ s y n t h e s i z e r _ d e s t r o y ( synthesizer ) ; return ER ROR_SY NTHESI ZER ; } 168 169 170 171 172 173 if ( fgets ( aux_vec , SIZE_AUX_VEC , file_synthesizer ) == NULL ) return ER ROR_SY NTHESI ZER ; 174 175 if ( ((* synthesizer ) -> harmonics = ( tharmonic **) malloc ( a u x _ q u a n t i t y _ h a r m o n i c * sizeof ( tharmonic *) ) ) == NULL ) { if ( ( a u x _ q u a n t i t y _ h a r m o n i c = strtoul ( aux_vec , NULL , 0) ) == 0) return ER ROR_SY NTHESI ZER ; 36 8.2 ADT synthesizer 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 A D T _ s y n t h e s i z e r _ d e s t r o y ( synthesizer ) ; return ERROR_NO_MEMORY ; } for ( i =0; i < a u x _ q u a n t i t y _ h a r m o n i c ; i ++) { if ( ((* synthesizer ) -> harmonics [ i ] = ( tharmonic *) malloc ( sizeof ( tharmonic ) ) ) == NULL ) { (* synthesizer ) -> qu antity _harmo nic = i ; A D T _ s y n t h e s i z e r _ d e s t r o y ( synthesizer ) ; return ERROR_NO_MEMORY ; } } for ( i =0; i < a u x _ q u a n t i t y _ h a r m o n i c ; i ++) { if ( fgets ( aux_vec , SIZE_AUX_VEC , file_synthesizer ) == NULL ) return ER ROR_SY NTHESI ZER ; 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 aux_string = strtok ( aux_vec , STRING_SPACE ) ; (* synthesizer ) -> harmonics [ i ] - > multiples_pairs = strtod ( aux_string , NULL ) ; aux_string = strtok ( NULL , STRING_SPACE ) ; (* synthesizer ) -> harmonics [ i ] - > intensity = strtod ( aux_string , NULL ) ; } for ( j =0; j < P H A S E _ M O D U L A T I O N _ A M O U N T ; j ++) { if ( fgets ( aux_vec , SIZE_AUX_VEC , file_synthesizer ) == NULL || ! strcmp ( aux_vec , " \ n " ) ) return ER ROR_SY NTHESI ZER ; aux_string = strtok ( aux_vec , STRING_SPACE ) ; if ( isdigit ( aux_vec [0]) ) return ER ROR_SY NTHESI ZER ; /* Caso especial : CONSTANT , no tiene par á metros */ L = strlen ( aux_vec ) -2; if ( aux_vec [ L +1] == ' \ n ' && L == strlen ( st ring_m odulat ors [0]) && ! strncmp ( aux_vec , strin g_modu lators [0] , L ) ) { (* synthesizer ) -> modulators [ j ] - > modulation = m o d u l a t i o n _ f u n c t i on s [0]; continue ; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ for ( i =0; i < Q U AN T I TY _ M OD U L AT O R S ; i ++) { if ( ! strcmp ( aux_string , st ring_m odulat ors [ i ]) ) { (* synthesizer ) -> modulators [ j ] - > modulation = m o d u l a t i o n _ f u n c t i o n s [ i ]; break ; } 227 228 229 230 231 232 233 234 } 37 8.2 ADT synthesizer for ( i =0; i < Q U AN T I TY _ P AR A M ET E R S && ( aux_string = strtok ( NULL , STRING_SPACE ) ) != NULL ; i ++) ((* synthesizer ) -> modulators [ j ] - > parameters [ i ]) = strtod ( aux_string , NULL ) ; 235 236 237 238 239 } 240 241 242 243 244 245 /* Validaci ó n */ for ( j =0; j < P H A S E _ M O D U L A T I O N _ A M O U N T ; j ++) { if ( (* synthesizer ) -> modulators [ j ] - > modulation == NULL ) return ER ROR_SY NTHESI ZER ; } 246 247 248 249 250 251 252 253 254 255 256 (* synthesizer ) -> qu antity _harmo nic = a u x _ q u a n t i t y _ h a r m o n i c ; fclose ( file_synthesizer ) ; return OK ; } /* | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 7) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | */ /* ||| || || || || || || || | Imprimir copia del archivo sintetizador || ||||| |||||||||| */ 257 /* | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | */ 258 259 260 261 262 263 264 265 266 267 268 status_t A D T _ s y n t h e s i z e r _ p r i n t ( const ADT_ synthe sizer_ t * synthesizer ) { size_t i , j , qua nt it y_ ha rm on ic s ; double multiples_pairs , intensity ; modulation_t modulation = NULL ; double * parameters = NULL ; double t ; if ( synthesizer == NULL ) return ERR OR _N UL L_ PO IN TE R ; 269 270 271 272 273 274 if ( ( q ua nt it y_ ha rm on ic s = A D T _ s y n t h e s i z e r _ g e t _ q u a n t i t y _ h a r m o n i c s ( synthesizer ) ) == 0) return ER ROR_SY NTHESI ZER ; 275 276 277 278 279 for ( i =0; i < qu an ti ty _h arm on ic s ; i ++) { if ( A D T _ s y n t h e s i z e r _ g e t _ h a r m o n i c _ a t ( synthesizer , i , & multiples_pairs , & intensity ) != OK ) return ERR OR_SY NTHESI ZER ; printf ( " %f %f \ n " , multiples_pairs , intensity ) ; } 280 281 282 283 284 285 printf ( " %lu \ n " , ( ulong ) qu ant it y_ ha rm on ic s ) ; 286 287 288 289 290 291 for ( i =0; i < P H A S E _ M O D U L A T I O N _ A M O U N T ; i ++) { for ( j =0; j < Q U AN T I TY _ M OD U L AT O R S ; j ++) { if ( synthesizer - > modulators [ i ] - > modulation == modulation_functions [j] ) printf ( " %s " , st ring_m odulat ors [ j ]) ; } for ( j =0; j < Q U AN T I TY _ P AR A M ET E R S ; j ++) printf ( " %f " , synthesizer - > modulators [ i ] - > parameters [ j ]) ; printf ( " \ n " ) ; } 292 293 printf ( " \ n %s \ n \ n " , " Prueba de funciones de modulacion : " ) ; 38 8.2 ADT synthesizer printf ( " %s \ n \ n " , " Ingrese el instante a evaluar : [ segundos ] " ) ; 294 295 296 297 298 if ( scanf ( " %lf " , & t ) != 1 ) return ER ROR_SY NTHESI ZER ; A D T _ s y n t h e s i z e r _ g e t _ m o d u l a t i o n _ a t ( synthesizer , ATTACK , & parameters , & modulation ) ; printf ( " Funcion de ataque evaluada en t = %f s --> %f \ n " , t , modulation ( parameters , t ) ) ; 299 300 301 302 303 304 A D T _ s y n t h e s i z e r _ g e t _ m o d u l a t i o n _ a t ( synthesizer , SUSTAINED , & parameters , & modulation ) ; printf ( " Funcion de duracion evaluada en t = %f s --> %f \ n " , t , modulation ( parameters , t ) ) ; 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 A D T _ s y n t h e s i z e r _ g e t _ m o d u l a t i o n _ a t ( synthesizer , RELEASE , & parameters , & modulation ) ; printf ( " Funcion de decaimiento evaluada en t = %f s --> %f \ n " , t , modulation ( parameters , t ) ) ; return OK ; } /* | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | */ /* | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | MAIN de prueba | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | */ /* | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | */ #if def TEST /* MAIN */ int main ( void ) { ADT_ synth esizer _t * synthesizer ; /* Creacion (1) */ if ( ( A DT _ s yn t h es i z er _ n ew (& synthesizer ) ) != OK ) { fprintf ( stderr , " Error en la creacion del sintetizador \ n " ) ; return EXIT_FAILURE ; } /* Llenado (6) */ if ( ( A D T _ s y n t h e s i z e r _ s e t _ f r o m _ f i l e (& synthesizer , FILE_NAME_TEST ) ) != OK ) { fprintf ( stderr , " Error en el seteo de los elementos \ n " ) ; return EXIT_FAILURE ; } /* Impresion (8) */ if ( ( A D T _ s y n t h e s i z e r _ p r i n t ( synthesizer ) ) != OK ) { fprintf ( stderr , " Error en la impresion de prueba \ n " ) ; return EXIT_FAILURE ; } /* Destruccion (2) */ A D T _ s y n t h e s i z e r _ d e s t r o y (& synthesizer ) ; return EXIT_SUCCESS ; 39 8.3 ADT wav file 353 354 355 356 } #endif 8.3. ADT wav file 8.3.1. ADT wav file.h 1 2 3 4 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Algoritmos y Programaci ó n I - 75.02/95.11 - Curso Ing . Mart ı́ n Cardozo TP N o 3 - 1 er Cuatrimestre 2012 5 6 7 8 9 10 11 12 13 14 15 Alumnos : ARIAS , Francisco - FERRARI BIHURRIET , Francisco Archivo : ADT_wav_file . h Descrip : Encabezado p ú blico para el TDA archivo WAV . Obs : * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include " ../ main_modules / common . h " 16 17 18 19 20 21 #if ndef ADT_WAV_FILE_H #define ADT_WAV_FILE_H 22 23 24 25 26 27 /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Prototipos | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | */ /* | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | */ typedef struct __wav_file * ADT_wav_file_t ; /* En el encabezado privado ... */ /* 1) Funci ó n para crear un archivo mono de 16 bit a partir de un ' double [] ' */ status_t A D T _ w a v _ f i l e _ c r e a t e _ f r o m _ v e c t o r ( uint , uint , double [] , 28 ADT_wav_file_t *) ; 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 /* 2) Funci ó n para destruir un archivo WAV */ status_t A D T _ w a v _ f i l e _ d e s t r o y ( ADT_wav_file_t *) ; /* 3) Funci ó n para escribir en un stream ( abierto en modo " wb ") */ status_t A DT _w av_ fi le _w ri te ( ADT_wav_file_t , FILE *) ; /* TODO : * * * * * */ #endif /* ADT_WAV_FILE_H */ 8.3.2. 1 ADT_wav_file_create_from_stream . ADT_wav_file_create_empty . ADT_wav_file_get_sample . ADT_wav_file_set_sample . ADT_wav_file_change_sample_rate . ADT wav file PRIVATE.h /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 40 8.3 ADT wav file 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 Algoritmos y Programaci ó n I - 75.02/95.11 - Curso Ing . Mart ı́ n Cardozo TP N o 3 - 1 er Cuatrimestre 2012 Alumnos : Archivo : Descrip : Obs : ARIAS , Francisco - FERRARI BIHURRIET , Francisco ADT_wav_file_PRIVATE .h Encabezado privado para el TDA archivo WAV . Para una correcta utilizaci ó n del TDA no debe conocerse el funcionamiento interno , el cu á l queda expuesto aqu ı́ . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include < limits .h > #include " ../ main_modules / common . h " #include " ADT_wav_file . h " #if ndef A D T _ W A V _ F I L E _ P R I V A T E _ H #define A D T _ W A V _ F I L E _ P R I V A T E _ H /* - - - - - - - - - - - - - - - - - - - - - - - - - Definiciones varias - - - - - - - - - - - - - - - - - - - - - - - #define WAV_ID_SIZES 4 /* Tama ~ n o en Bytes de los IDs . #define WAV_CHUNK_ID " RIFF " /* Identificador del Chunk principal . #define WAV_FORMAT " WAVE " /* Identificador del formato WAVE . #define WAV_SUBCHUNK1_ID " fmt " /* Identificador del 1 er SubChunk . #define WAV_SUBCHUNK2_ID " data " /* Identificador del 2 do SubChunk . /* ··································· */ #define W A V _ C H U N K _ F I X _ P A R T _ S I Z E 36 /* Tama ~ n o de la parte fija del Chunk . #define WA V_ SUB CH UN K1 _S IZ E 16 /* Tama ~ n o del 1 er SubChunk . #define WAV_AUDIO_FORMAT 1 /* Tipo de compresi ó n de audio ( PCM ) . #define WA V_MON O_CHAN NELS 1 /* Canales en MONO : solo uno . #define WAV_BITS_SAMPLE 16 /* Tama ~ n o de las muestras ( en bits ) . #define WAV_BYTES_SAMPLE ( WAV_BITS_SAMPLE / CHAR_BIT ) /* ( en bytes ) . /* ··································· */ #define MAX_INT16 ( pow (2 ,16) /2) /* ( m á ximo de un ' int16 ' ) . #define W A V _ M A X _ S A M P L E _ V A L U E ( MAX_INT16 -2) /* ( m á ximo valor absoluto ) . #define WA V_MAX_ N_SAM PLES (44100*2*3600) /* ( m á x : 2 h a 44 ,1 KHz ) . #define W AV _ M AX _ S AM P L E_ R A TE 192000 /* ( m á x frec . de muestreo ) . /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ /* - - - - - - - - - - - - - - - - - - - - - - - - Enumerativo de tipos - - - - - - - - - - - - - - - - - - - - - - - - */ typedef enum { TYPE_INT16 =2 , TYPE_INT32 =4} type_t ; /* No cambiar valores ! */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - Estructura del ADT_wav_file - - - - - - - - - - - - - - - - - - - - */ struct __wav_file { /* Chunk */ char ChunkID [ WAV_ID_SIZES ]; uint ChunkSize ; char Format [ WAV_ID_SIZES ]; /* SubChunk1 */ char SubChunk1ID [ WAV_ID_SIZES ]; uint SubChunk1Size ; uint AudioFormat ; uint NumChannels ; uint SampleRate ; uint ByteRate ; uint BlockAlign ; uint BitsPerSample ; 41 8.3 ADT wav file 62 63 64 65 66 67 68 69 70 71 72 73 /* SubChunk2 */ char SubChunk2ID [ WAV_ID_SIZES ]; uint SubChunk2Size ; short * Data ; }; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - Prototipos de funciones internas - - - - - - - - - - - - - - - - - - */ void _ w r i t e _ l i t t l e _ e n d i a n ( uint , type_t , FILE *) ; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #endif /* A D T _ W A V _ F I L E _ P R I V A T E _ H */ 8.3.3. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ADT wav file.c /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Algoritmos y Programaci ó n I - 75.02/95.11 - Curso Ing . Mart ı́ n Cardozo TP N o 3 - 1 er Cuatrimestre 2012 Alumnos : ARIAS , Francisco - FERRARI BIHURRIET , Francisco Archivo : ADT_wav_file . c Descrip : Implementaci ó n del TDA archivo WAV . Obs : * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #include < stdio .h > < string .h > < stdlib .h > < math .h > " ADT_wav_file_PRIVATE .h" /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 1) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | Creador | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ status_t A D T _ w a v _ f i l e _ c r e a t e _ f r o m _ v e c t o r ( uint n_samples , uint sample_rate , double vector [] , ADT_wav_file_t * wav_file ) { size_t i ; double scale ; /* Factor de escala */ 32 33 34 35 36 37 /* Validaciones de entrada */ if ( wav_file == NULL || vector == NULL ) if (! n_samples ) if ( n_samples > WA V_MAX_ N_SAMP LES ) if ( sample_rate > W AV _ M AX _ S AM P L E_ R A TE ) 38 39 40 41 42 /* Pedido de memoria y validaci ó n */ * wav_file = ( ADT_wav_file_t ) malloc ( sizeof ( struct __wav_file ) ) ; if (* wav_file == NULL ) return ERROR_NO_MEMORY ; 43 44 45 return return return return ERR OR _N UL L_ PO IN TE R ; ERR OR _I NV AL ID _I NF O ; E RR O R _T O O _L O N G_ F I LE ; ER ROR _I NV AL ID _I NF O ; /* - - - - - - - - - - - - - - - - Volcado de datos en Chunk - - - - - - - - - - - - - - - - */ memcpy ((* wav_file ) -> ChunkID , WAV_CHUNK_ID , WAV_ID_SIZES ) ; (* wav_file ) -> ChunkSize = W A V _ C H U N K _ F I X _ P A R T _ S I Z E + WAV_BYTES_SAMPLE * n_samples ; 42 8.3 ADT wav file memcpy ((* wav_file ) -> Format , WAV_FORMAT , WAV_ID_SIZES ) ; 46 47 48 49 50 /* - - - - - - - - - - - - - - Volcado de datos en SubChunk1 - - - - - - - - - - - - - - */ memcpy ((* wav_file ) -> SubChunk1ID , WAV_SUBCHUNK1_ID , WAV_ID_SIZES ) ; (* wav_file ) -> SubChunk1Size = WAV _S UB CH UN K1 _S IZ E ; (* wav_file ) -> AudioFormat = WAV_AUDIO_FORMAT ; (* wav_file ) -> NumChannels = WA V_MONO _CHANN ELS ; (* wav_file ) -> SampleRate = sample_rate ; (* wav_file ) -> ByteRate = WAV_BYTES_SAMPLE * sample_rate ; (* wav_file ) -> BlockAlign = WAV_BITS_SAMPLE ; (* wav_file ) -> BitsPerSample = WAV_BITS_SAMPLE ; 51 52 53 54 55 56 57 58 59 60 61 62 /* - - - - - - - - - - - - - - Volcado de datos en SubChunk2 - - - - - - - - - - - - - - */ memcpy ((* wav_file ) -> SubChunk2ID , WAV_SUBCHUNK2_ID , WAV_ID_SIZES ) ; (* wav_file ) -> SubChunk2Size = WAV_BYTES_SAMPLE * n_samples ; /* Pedido de memoria para las muestras y validaci ó n */ (* wav_file ) -> Data = ( short *) malloc ( n_samples * sizeof ( short ) ) ; if ((* wav_file ) -> Data == NULL ) { free (* wav_file ) ; return ERROR_NO_MEMORY ; } /* B ú squeda de m á ximo absoluto para evitar overflow */ scale = 0; for ( i =0; i < n_samples ; i ++) { if ( fabs ( vector [ i ]) > scale ) scale = fabs ( vector [ i ]) ; } /* C á lculo del factor de escala */ scale = W A V _ M A X _ S A M P L E _ V A L U E / scale ; /* Guardado de las muestras utilizando el factor de escala */ for ( i =0; i < n_samples ; i ++) ((* wav_file ) -> Data ) [ i ] = scale * vector [ i ]; 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 return OK ; } 86 87 88 89 90 /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 2) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | Destructor | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ 91 status_t A D T _ w a v _ f i l e _ d e s t r o y ( ADT_wav_file_t * wav_file ) 92 { 93 if ( wav_file == NULL || * wav_file == NULL ) return ERR OR _N UL L_ PO IN TE R ; 94 95 96 97 98 99 100 101 102 103 104 free ((* wav_file ) -> Data ) ; free (* wav_file ) ; * wav_file = NULL ; return OK ; } /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 3) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / | Escritor en archivo | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ 43 8.4 main modules 105 106 107 108 109 /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ status_t A DT _w av_ fi le _w ri te ( ADT_wav_file_t wav_file , FILE * stream ) { size_t i ; uint n_samples ; 110 111 112 113 114 115 if ( stream == NULL || wav_file == NULL ) return ERR OR _N UL L_ PO IN TE R ; /* - - - - - - - - - - - - - - - Escritura de datos en Chunk - - - - - - - - - - - - - - - */ fwrite (&( wav_file - > ChunkID ) , 1 , WAV_ID_SIZES , stream ) ; _ w r i t e _ l i t t l e _ e n d i a n ( wav_file - > ChunkSize , TYPE_INT32 , stream ) ; fwrite (&( wav_file - > Format ) , 1 , WAV_ID_SIZES , stream ) ; 116 117 118 119 120 121 /* ------- Escritura de datos en SubChunk1 ------*/ fwrite (&( wav_file - > SubChunk1ID ) , 1 , WAV_ID_SIZES , stream ) ; _ w r i t e _ l i t t l e _ e n d i a n ( wav_file - > SubChunk1Size , TYPE_INT32 , stream ) ; _ w r i t e _ l i t t l e _ e n d i a n ( wav_file - > AudioFormat , TYPE_INT16 , stream ) ; _ w r i t e _ l i t t l e _ e n d i a n ( wav_file - > NumChannels , TYPE_INT16 , stream ) ; _ w r i t e _ l i t t l e _ e n d i a n ( wav_file - > SampleRate , TYPE_INT32 , stream ) ; _ w r i t e _ l i t t l e _ e n d i a n ( wav_file - > ByteRate , TYPE_INT32 , stream ) ; _ w r i t e _ l i t t l e _ e n d i a n ( wav_file - > BlockAlign , TYPE_INT16 , stream ) ; _ w r i t e _ l i t t l e _ e n d i a n ( wav_file - > BitsPerSample , TYPE_INT16 , stream ) ; 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 /* ------- Escritura de datos en SubChunk2 ------*/ fwrite (&( wav_file - > SubChunk2ID ) , 1 , WAV_ID_SIZES , stream ) ; _ w r i t e _ l i t t l e _ e n d i a n ( wav_file - > SubChunk2Size , TYPE_INT32 , stream ) ; n_samples = ( wav_file - > SubChunk2Size ) / WAV_BYTES_SAMPLE ; for ( i =0; i < n_samples ; i ++) _ w r i t e _ l i t t l e _ e n d i a n (( wav_file - > Data ) [ i ] , TYPE_INT16 , stream ) ; return OK ; } 139 140 141 142 143 144 /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | *) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / | Funciones internas | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ void _ w r i t e _ l i t t l e _ e n d i a n ( uint value , type_t type , FILE * stream ) 145 { 146 uchar convert [ TYPE_INT32 ] , i ; 147 148 149 150 151 152 153 /* En ' type_t ' cada tipo tiene asignada la cantidad de bytes ! */ for ( i =0; i < type ; i ++) convert [ i ]=( value &( UCHAR_MAX < < i * CHAR_BIT ) ) >>i * CHAR_BIT ; fwrite (& convert , 1 , type , stream ) ; } main modules 8.4. 8.4.1. 1 2 3 4 5 6 addsynthlib.h /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Algoritmos y Programaci ó n I - 75.02/95.11 - Curso Ing . Mart ı́ n Cardozo TP N o 3 - 1 er Cuatrimestre 2012 Alumnos : ARIAS , Francisco - FERRARI BIHURRIET , Francisco 44 8.4 main modules 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 Archivo : addsynthlib . h Descrip : Encabezado de la biblioteca de s ı́ ntesis aditiva . Obs : * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #if ndef ADDSYNTHLIB_H #define ADDSYNTHLIB_H #include < stdio .h > #include " ../ ADT_synthesizer / ADT_synthesizer . h " #include " ../ ADT_ musica l_scor e / ADT_ musica l_scor e . h " #define TWOPI 2 * 3 . 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 2 3 8 4 6 typedef struct { double * values ; size_t sample_rate ; } tabsin_t ; /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Prototipos | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | */ /* | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | */ /* 1) Funci ó n para crear la tabla con el seno precalculado */ tabsin_t * t a b si n _ cr e a te _ t ab l e ( size_t ) ; /* 2) Funci ó n para destruir la tabla */ void t a b s i n _ d e s t r o y _ t a b l e ( tabsin_t **) ; /* 3) Funci ó n para obtener la envolvente en funci ó n del tiempo */ double evenlope ( const AD T_synt hesize r_t * , const A DT _ m us i c al _ s co r e _t * , double , size_t ) ; /* 4) Funci ó n para sintetizar una partitura completa */ void synthesize ( const A DT _ m us i c al _ s co r e _t * , const AD T_synt hesize r_t * , tabsin_t * , double []) ; #endif /* ADDSYNTHLIB_H */ 8.4.2. 1 2 3 4 5 6 7 8 9 10 11 12 addsynthlib.c /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Algoritmos y Programaci ó n I - 75.02/95.11 - Curso Ing . Mart ı́ n Cardozo TP N o 3 - 1 er Cuatrimestre 2012 Alumnos : Archivo : Descrip : Obs : ARIAS , Francisco - FERRARI BIHURRIET , Francisco addsynthlib . c Biblioteca de s ı́ ntesis aditiva . Contiene rutinas que utilizan la funci ó n seno tabulada seg ú n la frecuancia de muestreo , para optimizar la velocidad de s ı́ ntesis . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 13 14 45 8.4 main modules 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include #include #include #include #include /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 1) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* |/////////| Funci ó n para crear la tabla con el seno precalculado |\\\\\\\\\| */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ tabsin_t * t a b si n _ cr e a te _ t ab l e ( size_t sample_rate ) { tabsin_t * ptable ; size_t i ; double aux ; /* Memoria para la estructura */ ptable = ( tabsin_t *) malloc ( sizeof ( tabsin_t ) ) ; if ( ptable == NULL ) return NULL ; 32 33 34 35 36 /* Memoria para la tabla */ ptable - > values = ( double *) malloc ( sample_rate * sizeof ( double ) ) ; if ( ptable - > values == NULL ) { free ( ptable ) ; return NULL ; } 37 38 39 40 41 42 ptable - > sample_rate = sample_rate ; 43 44 45 46 47 48 49 50 51 52 53 54 < stdio .h > < stdlib .h > < math .h > " addsynthlib . h " " common . h " aux = TWOPI / ( sample_rate -1) ; /* Cargado de la tabla */ for ( i =0; i < sample_rate ; i ++) ( ptable - > values ) [ i ] = sin ( i * aux ) ; return ptable ; } 55 56 57 58 59 /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 2) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / | Funci ó n para destruir la tabla | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ void t a b s i n _ d e s t r o y _ t a b l e ( tabsin_t ** table ) 60 { 61 if ( table == NULL || * table == NULL ) return ; 62 63 64 65 66 67 68 69 70 71 free ((* table ) -> values ) ; free (* table ) ; * table = NULL ; } /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 3) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* |///////| Funci ó n para obtener la envolvente en funci ó n del tiempo |\\\\\\\| */ 72 /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ 73 #define ATTACK_TIME p aramet ers_at tack [ param_T0 ] 46 8.4 main modules 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 #define RELEASE_TIME pa ra me ter s_ re le as e [ param_T0 ] double evenlope ( const AD T_synt hesize r_t * synthesizer , const A D T _m u s ic a l _s c o re _ t * musical_score , double t , size_t note ) { modulation_t mo dulati on_at tack ; modulation_t m o d u l a t i o n _ s u s t a i n e d ; modulation_t mo du lat io n_ re le as e ; double * pa ramete rs_att ack ; double * p a r a m e t e r s _ s u s t a i n e d ; double * par am et er s_ re le as e ; double duration ; if ( synthesizer == NULL || musical_score == NULL ) return 0; if ( ( A D T _ s y n t h e s i z e r _ g e t _ m o d u l a t i o n _ a t ( synthesizer , ATTACK , & parameters_attack , & modul ation_ attack ) ) != OK ) return 0; if ( ( A D T _ s y n t h e s i z e r _ g e t _ m o d u l a t i o n _ a t ( synthesizer , SUSTAINED , & parameters_sustained , & m o d u l a t i o n _ s u s t a i n e d ) ) != OK ) return 0; if ( ( A D T _ s y n t h e s i z e r _ g e t _ m o d u l a t i o n _ a t ( synthesizer , RELEASE , & parameters_release , & mo du la ti on _r el ea se ) ) != OK ) return 0; 91 92 93 94 95 96 97 98 99 100 101 duration = A D T _ m u s i c a l _ s c o r e _ g e t _ d u r a t i o n _ a t ( musical_score , note ) ; 102 103 104 105 106 107 if ( t < ATTACK_TIME ) return mo dulati on_att ack ( parameters_attack , t ) ; if ( t >= ATTACK_TIME && t < duration ) return m o d u l a t i o n _ s u s t a i n e d ( parameters_sustained , t - ATTACK_TIME ) ; 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 if ( t >= duration && t < duration + RELEASE_TIME ) return m o d u l a t i o n _ s u s t a i n e d ( parameters_sustained , duration - ATTACK_TIME ) * mo du la ti on _r el ea se ( parameters_release , t - duration ) ; return 0; } /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 4) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* |////////////| Funci ó n para sintetizar una partitura completa |\\\\\\\\\\\\| */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* Precondici ó n : El vector de doubles alcanza , es decir que ya fue pedida la memoria para toda la canci ó n . */ void synthesize ( const A DT _ m us i c al _ s co r e _t * musical_score , const ADT_s ynthes izer_t * synth , tabsin_t * table , double samples_vec []) { size_t i , harmonic , n_harmonics , note , n_notes ; double T ; /* Per ı́ odo en muestras */ uint init_sample , n_samples ; double harmonic_multiple , ha rmo ni c_ in te ns it y ; 47 8.4 main modules double * release_time ; 133 134 135 136 137 if ( musical_score == NULL || synth == NULL || table == NULL || samples_vec == NULL ) return ; /* Se obtiene el release_time */ A D T _ s y n t h e s i z e r _ g e t _ m o d u l a t i o n _ a t ( synth , RELEASE , & release_time , NULL ) ; /* Se obtiene el n ú mero de arm ó nicos */ n_harmonics = A D T _ s y n t h e s i z e r _ g e t _ q u a n t i t y _ h a r m o n i c s ( synth ) ; /* Se obtiene la cantidad de notas */ n_notes = A D T _ m u s i c a l _ s c o r e _ g e t _ q u a n t i t y _ n o t e s ( musical_score ) ; 138 139 140 141 142 143 144 145 146 147 148 149 /* -- Para cada nota -- */ for ( note =0; note < n_notes ; note ++) { /* Se obtiene la muestra inicial */ init_sample = A D T _ m u s i c a l _ s c o r e _ g e t _ s t a r t _ t i m e _ a t ( musical_score , note ) * table - > sample_rate ; /* Se obtiene la cantidad de muestras */ n_samples = ( A D T _ m u s i c a l _ s c o r e _ g e t _ d u r a t i o n _ a t ( musical_score , note ) + * release_time ) * table - > sample_rate ; 150 151 152 153 154 /* -- S ı́ ntesis : Para cada arm ó nico -- */ for ( harmonic =0; harmonic < n_harmonics ; harmonic ++) { /* Se obtiene el m ú ltiplo y la intensidad */ A D T _ s y n t h e s i z e r _ g e t _ h a r m o n i c _ a t ( synth , harmonic , & harmonic_multiple , & ha rm on ic _i nt en si ty ) ; /* Asignaci ó n del per ı́ odo en muestras */ T = table - > sample_rate / ( A D T _ m u s i c a l _ s c o r e _ g e t _ f r e q u e n c y _ a t ( musical_score , note ) * harmo nic_mu ltiple ) ; 155 156 157 158 159 160 161 162 163 164 165 166 /* -- Para cada muestra -- */ for ( i =0; i < n_samples ; i ++) { samples_vec [ i + init_sample ] += h ar mo ni c_ in ten si ty * ( table - > values ) /* Uso del seno tabulado : */ [ ( size_t ) ( ( i / T - floor ( i / T ) ) * table - > sample_rate ) ] * evenlope ( synth , musical_score , i /( double ) table - > sample_rate , note ) ; } 167 168 169 170 171 172 173 174 175 176 177 } } } 8.4.3. 1 2 3 4 5 6 7 8 9 10 11 12 common.h /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Algoritmos y Programaci ó n I - 75.02/95.11 - Curso Ing . Mart ı́ n Cardozo TP N o 3 - 1 er Cuatrimestre 2012 Alumnos : ARIAS , Francisco - FERRARI BIHURRIET , Francisco Archivo : common . h Descrip : Encabezado de definiciones comunes a todos los m ó dulos . Obs : * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 48 8.4 main modules 13 14 15 16 17 #if ndef COMMON_H #define COMMON_H /* - - - - - - - - - - - - - - - - - - - - - - - Abreviaturas de tipos - - - - - - - - - - - - - - - - - - - - - - - */ typedef unsigned char uchar ; typedef unsigned short ushort ; typedef unsigned int uint ; typedef unsigned long ulong ; typedef char * string ; 24 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 18 19 20 21 22 23 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 /* - - - - - - - - - - - - - - - - - - - - - - - Enumerativo de estado - - - - - - - - - - - - - - - - - - - - - - - */ typedef enum { OK = 0 , /* Ning ú n error ha ocurrido . */ E R RO R _ BA D _ AR G U ME N T S = 1 , /* Error de argumentos incorrectos . */ E R R O R _ B A D _ S A M P L E _ R A T E = 2 , /* Error de frecuencia de muestreo . */ E R RO R _ MU S I CA L _ SC O R E = 3 , /* Error en el archivo de partitura . */ ERRO R_SYNT HESIZE R = 4 , /* Error en el archivo de sintetizador . */ ER RO R_ NU LL _P OI NT ER = 5 , /* Error de puntero nulo . */ ER RO R_ IN VA LI D_ IN FO = 6 , /* Error de informaci ó n inv á lida . */ ERROR_NO_MEMORY = 7 , /* Error de falta de memoria . */ E R RO R _ TO O _ LO N G _F I L E = 8 , /* Error de archivo demasiado largo . */ ERROR_WAV_FILE = 9 /* Error en el archivo WAV . */ } status_t ; /* ··································· */ extern const string status_msgs []; /* Mensajes en archivo externo . */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - Enumerativo de progreso - - - - - - - - - - - - - - - - - - - - - - */ typedef enum { PROGRESS_PREVIOUS_TASKS = 0, /* Tareas previas . */ PROGRESS_MUSIC_SYNTHESIS = 1, /* S ı́ ntesis de la m ú sica . */ P R O G R E S S _ O U T _ F I L E _ C R E A T I O N = 2 , /* Creaci ó n del archivo de salida . */ PROGRESS_DUMP_OF_DATA = 3, /* Volcado de datos . */ PROGRESS_FILE_CREATED = 4 /* Archivo creado . */ } progress_t ; /* ··································· */ extern const string progress_msgs []; /* Mensajes en archivo externo . */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - Mensajes de uso - - - - - - - - - - - - - - - - - - - - - - - - - - */ #define USAGE_USAGE 0 /* Uso . */ #define US AGE_SA MPLE_ RATE 1 /* Frecuencia de muestreo . */ #define U S A G E _ F I L E _ M U S I C A L _ S C O R E 2 /* Archivo de partitura musical . */ #define U S A G E _ F I L E _ S Y N T H E S I Z E R 3 /* Archivo de sintetizador . */ #define USAGE_FILE_WAVE 4 /* Archivo de audio ( WAV ) . */ /* ··································· */ extern const string usage_msgs []; /* Mensajes en archivo externo . */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - Validate arguments - - - - - - - - - - - - - - - - - - - - - - - - - - */ 49 8.4 main modules #define A R G U M E N T _ S A M P L E _ R A T E " -f " #define A R G U M E N T _ F I L E _ M U S I C A L _ S C O R E " -p " #define A R G U M E N T _ F I L E _ S Y N T H E S I Z E R " -s " #define AR GU ME NT_ FI LE _W AV E " -o " #define D EF A U LT _ S AM P L E_ R A TE 44100 /* Hz */ 77 #define MAX_SAMPLE_RATE 96000 /* Hz */ 78 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 72 73 74 75 76 79 80 #endif /* COMMON_H */ 8.4.4. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 main.c /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Algoritmos y Programaci ó n I - 75.02/95.11 - Curso Ing . Mart ı́ n Cardozo TP N o 3 - 1 er Cuatrimestre 2012 Alumnos : ARIAS , Francisco - FERRARI BIHURRIET , Francisco Archivo : main . c Descrip : M ó dulo principal de la aplicaci ó n . Obs : * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include 18 #include 19 #include 20 #include 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 < stdio .h > < stdlib .h > < string .h > " ../ ADT_ musica l_scor e / ADT_ musica l_scor e . h " " ../ ADT_synthesizer / ADT_synthesizer . h " " ../ ADT_wav_file / ADT_wav_file . h " " addsynthlib . h " typedef struct { string musical_score ; string synthesizer ; string wave ; } tfiles_names ; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * PROTOTYPES * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* 1) validacion de argumentos */ status_t v al id ate _a rg um en ts ( int , string [] , tfiles_names * , size_t *) ; /* 2) Impresores de errores y estados */ void progress_msg ( progress_t ) ; void status_msg ( status_t ) ; void show_usage ( void ) ; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ string program_name ; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * FUNCTION MAIN * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int main ( int argc , string argv []) { /* **** - - - - - - - - - - - - - - - - - - - - - - - - - - - variables - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -**** */ 50 8.4 main modules 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 status_t st ; size_t sample_rate , note , quantity_notes ; tfiles_names files_names ; A DT _ m us i c al _ s co r e _t * musical_score ; ADT_ synthe sizer _t * synthesizer ; ADT_wav_file_t wav_file ; uint n_samples ; double * samples_vec ; double * release ; double time_length , aux ; FILE * out_file ; tabsin_t * table ; /* **** - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -**** */ /* Validacion de argumentos */ program_name = * argv ; st = v al id at e_ ar gu me nt s ( argc , argv , & files_names , & sample_rate ) ; if ( st != OK ) { status_msg ( st ) ; show_usage () ; return st ; } progress_msg ( P R O G R E S S _ P R E V I O U S _ T A S K S ) ; /* Creacion de los TDA partitura y sintetizador */ if ( ( st = A D T _ m u s i c a l _ s c o r e _ n e w (& musical_score ) ) != OK ) { status_msg ( st ) ; return st ; } if ( ( st = A DT _ s yn t h es i z er _ n ew (& synthesizer ) ) != OK ) { A D T _ m u s i c a l _ s c o r e _ d e s t r o y (& musical_score ) ; status_msg ( st ) ; return st ; } /* Cargar el contenido de los archivos en los TDA */ if ( ( st = A D T _ m u s i c a l _ s c o r e _ s e t _ f r o m _ f i l e (& musical_score , files_names . musical_score ) ) != OK ) { A D T _ s y n t h e s i z e r _ d e s t r o y (& synthesizer ) ; status_msg ( st ) ; return st ; } if ( ( st = A D T _ s y n t h e s i z e r _ s e t _ f r o m _ f i l e (& synthesizer , files_names . synthesizer ) ) != OK ) { A D T _ m u s i c a l _ s c o r e _ d e s t r o y (& musical_score ) ; status_msg ( st ) ; return st ; } 51 8.4 main modules 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 /* | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | */ /* | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | */ /* Otenci ó n del tiempo de duraci ó n de la canci ó n */ time_length = 0; quantity_notes = A D T _ m u s i c a l _ s c o r e _ g e t _ q u a n t i t y _ n o t e s ( musical_score ) ; for ( note = 0; note < quantity_notes ; note ++) { aux = A D T _ m u s i c a l _ s c o r e _ g e t _ s t a r t _ t i m e _ a t ( musical_score , note ) + A D T _ m u s i c a l _ s c o r e _ g e t _ d u r a t i o n _ a t ( musical_score , note ) ; if ( aux > time_length ) time_length = aux ; } /* Suma del release time */ A D T _ s y n t h e s i z e r _ g e t _ m o d u l a t i o n _ a t ( synthesizer , RELEASE , & release , NULL ) ; time_length += (* release ) ; /* Otenci ó n de la cantidad de muestras total */ n_samples = time_length * sample_rate + 1; /* Pedido para las muestras inicializadas en 0 */ samples_vec = ( double *) calloc ( n_samples , sizeof ( double ) ) ; if ( samples_vec == NULL ) { A D T _ m u s i c a l _ s c o r e _ d e s t r o y (& musical_score ) ; A D T _ s y n t h e s i z e r _ d e s t r o y (& synthesizer ) ; status_msg ( ERROR_NO_MEMORY ) ; return ERROR_NO_MEMORY ; } /* Creado de la tabla del seno precalculado */ table = t a b si n _ cr e a te _ t ab l e ( sample_rate ) ; if ( table == NULL ) { free ( samples_vec ) ; A D T _ m u s i c a l _ s c o r e _ d e s t r o y (& musical_score ) ; A D T _ s y n t h e s i z e r _ d e s t r o y (& synthesizer ) ; status_msg ( ERROR_NO_MEMORY ) ; return ERROR_NO_MEMORY ; } /* Sintetizado de la partitura */ progress_msg ( P R O G R E S S _ M U S I C _ S Y N T H E S I S ) ; synthesize ( musical_score , synthesizer , table , samples_vec ) ; /* Liberaci ó n de lo que ya no se utilizar á : tabla de senos y TDAs */ t a b s i n _ d e s t r o y _ t a b l e (& table ) ; A D T _ m u s i c a l _ s c o r e _ d e s t r o y (& musical_score ) ; A D T _ s y n t h e s i z e r _ d e s t r o y (& synthesizer ) ; /* Creaci ó n del TDA Archivo WAV */ progress_msg ( P R O G R E S S _ O U T _ F I L E _ C R E A T I O N ) ; st = A D T _ w a v _ f i l e _ c r e a t e _ f r o m _ v e c t o r ( n_samples , sample_rate , samples_vec , & wav_file ) ; /* Liberaci ó n de las muestras en double */ free ( samples_vec ) ; if ( st != OK ) 52 8.4 main modules 167 168 169 170 171 { 172 173 174 175 176 177 /* Apertura del archivo de salida */ out_file = fopen ( files_names . wave , " wb " ) ; if ( out_file == NULL ) { A D T _ w a v _ f i l e _ d e s t r o y (& wav_file ) ; status_msg ( ERROR_WAV_FILE ) ; return ERROR_WAV_FILE ; } status_msg ( st ) ; return st ; } 178 179 180 181 182 183 /* Escritura del archivo de salida */ progress_msg ( P R O G R E S S _ D U M P _ O F _ D A T A ) ; st = A DT _w av _f il e_ wr it e ( wav_file , out_file ) ; 184 185 186 187 188 /* Cierre del archivo de salida */ fclose ( out_file ) ; if ( st != OK ) { A D T _ w a v _ f i l e _ d e s t r o y (& wav_file ) ; status_msg ( st ) ; return st ; } 189 190 191 192 193 194 /* Destrucci ó n del TDA Archivo WAV */ st = A D T _ w a v _ f i l e _ d e s t r o y (& wav_file ) ; 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 fputc ( ' \ n ' , stderr ) ; status_msg ( st ) ; fprintf ( stderr , " %s : ' %s ' .\ n \ n " , progress_msgs [ P R O G R E S S _ F I L E _ C R E A T E D ] , files_names . wave ) ; return st ; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 1) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / | Validacion de argumentos | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* Macro de fuci ó n : es impar ? */ #define ISODD ( n ) (( n ) %2) /* - - - - - - - - - - - - - - - - - - - - - - - - - - */ status_t v al id ate _a rg um en ts ( int argc , string argv [] , tfiles_names * files_names , size_t * sample_rate ) { 218 size_t i ; 219 220 221 222 223 /* Los argumentos estan dados de a pares , sumando el nombre del programa , lo correcto es un n ú mero impar . */ if (! ISODD ( argc ) ) return E RR O R _B A D _A R G UM E N TS ; 224 225 * sample_rate = 0; 53 8.4 main modules files_names - > musical_score = NULL ; files_names - > synthesizer = NULL ; files_names - > wave = NULL ; 226 227 228 229 230 /* B ú squeda de argumentos */ for ( i = 1; i < argc ; i += 2) { if ( ! strcmp ( argv [ i ] , A R G U M E N T _ F I L E _ M U S I C A L _ S C O R E ) ) files_names - > musical_score = argv [ i +1]; 231 232 233 234 235 236 if ( ! strcmp ( argv [ i ] , A R G U M E N T _ F I L E _ S Y N T H E S I Z E R ) ) files_names - > synthesizer = argv [ i +1]; 237 238 239 240 241 242 if ( ! strcmp ( argv [ i ] , ARG UM EN T_ FI LE _W AV E ) ) files_names - > wave = argv [ i +1]; if ( ! strcmp ( argv [ i ] , A R G U M E N T _ S A M P L E _ R A T E ) ) * sample_rate = strtoul ( argv [ i +1] , NULL ,10) ; 243 244 245 246 247 } /* Si los par á metros obligatorios no fueron ingresados */ if ( files_names - > musical_score == NULL || files_names - > synthesizer == NULL || files_names - > wave == NULL ) return E RR O R _B A D _A R G UM E N TS ; 248 249 250 251 252 253 /* Si el par á metro opcional no fue ingresado */ if (!(* sample_rate ) ) * sample_rate = D E FA U L T _S A M PL E _ RA T E ; 254 255 256 257 258 259 260 261 262 263 264 265 /* Validaci ó n de m á xima frecuencia de muestreo */ if ( * sample_rate > MAX_SAMPLE_RATE ) return E R R O R _ B A D _ S A M P L E _ R A T E ; return OK ; } /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | 2) | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ /* | / / / / / / / / / / / / / / / / / / / / | Impresores de errores y estados | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\ \ \ | */ 266 /* | / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / | \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | */ 267 268 269 270 void progress_msg ( progress_t pg ) { fprintf ( stderr , " \ n %s ... " , progress_msgs [ pg ]) ; 271 } 272 273 274 275 276 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ void status_msg ( status_t st ) { 277 fprintf ( stderr , " %s \ n " , status_msgs [ st ]) ; 278 } 279 280 281 282 283 284 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ void show_usage ( void ) { fprintf ( stderr , " \ n %s : %s [ %s < %s >] %s < %s > %s < %s > %s < %s >\ n \ n " , 54 8.5 langs usage_msgs [ USAGE_USAGE ] , ARGUMENT_SAMPLE_RATE , ARGUMENT_FILE_MUSICAL_SCORE , ARGUMENT_FILE_SYNTHESIZER , ARGUMENT_FILE_WAVE , 285 286 287 288 289 290 } 8.5. langs 8.5.1. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 program_name , usage_msgs [ USAGE _SAMPL E_RAT E ] , usage_msgs [ U S A G E _ F I L E _ M U S I C A L _ S C O R E ] , usage_msgs [ U S A G E _ F I L E _ S Y N T H E S I Z E R ] , usage_msgs [ USAGE_FILE_WAVE ]) ; msgs dictionary es.c /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Algoritmos y Programaci ó n I - 75.02/95.11 - Curso Ing . Mart ı́ n Cardozo TP N o 3 - 1 er Cuatrimestre 2012 Alumnos : ARIAS , Francisco - FERRARI BIHURRIET , Francisco Archivo : ms gs _di ct io na ry _e s . c Descrip : Diccionario de mensajes al usuario en idioma castellano . Obs : * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include < stdio .h > #include " ../ main_modules / common . h " /* - - - - - - - - - - - - - - - - - - - - - - - - - Mensajes de estado - - - - - - - - - - - - - - - - - - - - - - - - - */ const string status_msgs []= { " Ok . " , " Error ! Codigo 1: Argumentos incorrectos . " , " Error ! Codigo 2: Frecuencia de muestreo incorrecta . " , " Error ! Codigo 3: En el archivo de partitura . " , " Error ! Codigo 4: En el archivo de sintetizador . " , " Error ! Codigo 5: Se recibio un puntero nulo ! " , " Error ! Codigo 6: Informacion invalida ! " , " Error ! Codigo 7: Memoria insuficiente ! " , " Error ! Codigo 8: Archivo demasiado largo ! " , " Error ! Codigo 9: No se pudo abrir el archivo WAV ! Esta en uso ? " }; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - Mensajes de progreso - - - - - - - - - - - - - - - - - - - - - - - - */ const string progress_msgs []= { " Realizando tareas previas " , " Sintetizando la musica " , " Creando el archivo de salida " , " Volcando los datos en el archivo " , " Archivo escrito " }; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - Mensajes de uso - - - - - - - - - - - - - - - - - - - - - - - - - - */ const string usage_msgs []= { 47 " Uso " , 48 " frecuencia " , 49 " partitura . txt " , 55 8.5 langs 50 51 52 53 " sintetizador . txt " , " audio . wav " }; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 8.5.2. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 msgs dictionary en.c /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Algoritmos y Programaci ó n I - 75.02/95.11 - Curso Ing . Mart ı́ n Cardozo TP N o 3 - 1 er Cuatrimestre 2012 Alumnos : ARIAS , Francisco - FERRARI BIHURRIET , Francisco Archivo : ms gs _di ct io na ry _e n . c Descrip : Diccionario de mensajes al usuario en idioma ingl é s . Obs : * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include < stdio .h > #include " ../ main_modules / common . h " /* - - - - - - - - - - - - - - - - - - - - - - - - - Mensajes de estado - - - - - - - - - - - - - - - - - - - - - - - - - */ const string status_msgs []= { " Ok . " , " Error ! Code 1: Incorrect arguments . " , " Error ! Code 2: Incorrect sample rate . " , " Error ! Code 3: In the musical score file . " , " Error ! Code 4: In the synthesizer file . " , " Error ! Code 5: A null pointer was received ! " , " Error ! Code 6: Invalid information ! " , " Error ! Code 7: Insufficient memory ! " , " Error ! Code 8: Too long file ! " , " Error ! Code 9: Could not open the WAV file ! In use ? " }; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - Mensajes de progreso - - - - - - - - - - - - - - - - - - - - - - - - */ const string progress_msgs []= { " Performing previous work " , " Synthesizing the music " , " Creating the output file " , " Flushing the data in the file " , 40 " File written " 41 }; 42 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 34 35 36 37 38 39 43 44 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - Mensajes de uso - - - - - - - - - - - - - - - - - - - - - - - - - - */ const string usage_msgs []= { " Usage " , " sample_rate " , " musical_score . txt " , " synthesizer . txt " , 51 " audio . wav " 52 }; 53 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 45 46 47 48 49 50 56 8.6 Makefile 8.6. Makefile 8.6.1. Makefile 1 2 3 4 5 6 7 # ******************************************************************************* # # # # # 8 # 9 # 10 # 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 Algoritmos y Programaci ó n I - 75.02/95.11 - Curso Ing . Mart ı́ n Cardozo TP N o 3 - 1 er Cuatrimestre 2012 Alumnos : Archivo : Descrip : Obs : ARIAS , Francisco - FERRARI BIHURRIET , Francisco Makefile Makefile para la construcci ó n de la aplicaci ó n completa . Admite la compilaci ó n para distintos idiomas . Los mismos son configurables en el archivo lang . # ******************************************************************************* # //////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ # # | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Configuraciones | | | | | | | | | | | | | | | | | | | | | | | | | | | | | # # \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\////////////////////////////////////// # # Compilador : CC = gcc # Flags para linkeo : LFLAGS = - ansi - pedantic - Wall # Flags para compilacion : CFLAGS = - ansi - pedantic - Wall - O3 -c # Nombre de salida del proyecto : OUT = synthesizer # Directorio de instalacion : INSTALL_PATH = / usr / bin # Idioma por defecto : LANG = en # Archivo de idioma : include lang # //////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ # # | | | | | | | | | | | | | | | | | | | | | | | | | Objetivos y dependencias | | | | | | | | | | | | | | | | | | | | | | | | | # 37 # \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / # 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 # - - - - - - - - - - - - - - - - - - - - - - - - - - Codigos objeto - - - - - - - - - - - - - - - - - - - - - - - - - - # OBJETS = ADT _music al_sco re . o \ ADT_synthesizer . o \ modulationlib . o \ ADT_wav_file . o \ addsynthlib . o \ main . o \ msgs_dictionary . o # - - - - - - - - - - - - - - - - - - - - - - Reglas de construccion - - - - - - - - - - - - - - - - - - - - - - # $ ( OUT ) : $ ( OBJETS ) $ ( CC ) $ ( LFLAGS ) $ ( OBJETS ) -o " $ ( OUT ) " - lm ADT_ musica l_sco re . o : ADT _music al_sco re / ADT _music al_sco re . c \ ADT _music al_sco re / A D T _ m u s i c a l _ s c o r e _ P R I V A T E . h \ ADT _music al_sco re / ADT _music al_sco re . h \ 57 8.6 Makefile 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 main_modules / common . h $ ( CC ) $ ( CFLAGS ) " $ < " -o " $ @ " ADT_synthesizer . o : ADT_synthesizer / ADT_synthesizer . c ADT_synthesizer / A D T _ s y n t h e s i z e r _ P R I V A T E . h ADT_synthesizer / ADT_synthesizer . h ADT_synthesizer / modulationlib . h main_modules / common . h $ ( CC ) $ ( CFLAGS ) " $ < " -o " $ @ " \ \ \ \ modulationlib . o : \ ADT_wav_file . o : \ \ \ addsynthlib . o : \ \ \ \ \ main . o : main_modules / main . c ADT _music al_sco re / ADT _music al_sco re . h ADT_synthesizer / ADT_synthesizer . h ADT_synthesizer / modulationlib . h ADT_wav_file / ADT_wav_file . h main_modules / addsynthlib . h main_modules / common . h $ ( CC ) $ ( CFLAGS ) " $ < " -o " $ @ " \ \ \ \ \ \ langs / msgs_ dictio nary_ $ ( LANG ) . c lang main_modules / common . h $ ( CC ) $ ( CFLAGS ) " $ < " -o " $ @ " \ \ ADT_synthesizer / modulationlib . c ADT_synthesizer / modulationlib . h $ ( CC ) $ ( CFLAGS ) " $ < " -o " $ @ " ADT_wav_file / ADT_wav_file . c ADT_wav_file / A D T _ w a v _ f i l e _ P R I V A T E . h ADT_wav_file / ADT_wav_file . h main_modules / common . h $ ( CC ) $ ( CFLAGS ) " $ < " -o " $ @ " main_modules / addsynthlib . c main_modules / addsynthlib . h ADT _music al_sco re / ADT _music al_sco re . h ADT_synthesizer / ADT_synthesizer . h ADT_synthesizer / modulationlib . h main_modules / common . h $ ( CC ) $ ( CFLAGS ) " $ < " -o " $ @ " msgs_dictionary . o : # //////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ # # | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Utilidades extras | | | | | | | | | | | | | | | | | | | | | | | | | | | | # # \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\////////////////////////////////////// # # - - - - - - - - - - - - - - - - - - - - - - Limpiar c ó digos objeto - - - - - - - - - - - - - - - - - - - - - - # objclean : rm -f *. o # - - - - - - - - - - - - - - - - - - - - - - - - - - Limpiar ( todo ) - - - - - - - - - - - - - - - - - - - - - - - - - - # clean : objclean rm -f " $ ( OUT ) " # - - - - - - - - - - - - - Construir y eliminar archivos temporales - - - - - - - - - - - - - # deltemps : $ ( OUT ) objclean 58 8.6 Makefile 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Instalar - - - - - - - - - - - - - - - - - - - - - - - - - - - - # install : $ ( OUT ) @ cp " $ ( OUT ) " " $ ( INSTALL_PATH ) " @ echo " '$ ( OUT ) ' --> Installed in : $ ( INSTALL_PATH ) " # - - - - - - - - - - - - - - - - - - - - - Todo ( instalar y limpiar ) - - - - - - - - - - - - - - - - - - - - # all : install clean # - - - - - - - - - - - - - - - - - - - - - - - - - - - - Desinstalar - - - - - - - - - - - - - - - - - - - - - - - - - - - # remove : rm -f " $ ( INSTALL_PATH ) / $ ( OUT ) " # - - - - - - - - - - - - - - - - - - Purgar ( desinstalar y limpiar ) - - - - - - - - - - - - - - - - - - # purge : remove clean 8.6.2. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 lang # ******************************************************************************* # # # # # # # # Algoritmos y Programaci ó n I - 75.02/95.11 - Curso Ing . Mart ı́ n Cardozo TP N o 3 - 1 er Cuatrimestre 2012 Alumnos : Archivo : Descrip : Obs : ARIAS , Francisco - FERRARI BIHURRIET , Francisco lang Selector del idioma a utilizar en la compilaci ó n con ' make ' . Si se dejan todas las opciones comentadas el programa asumir á el idioma por defecto . # ******************************************************************************* # Para idioma castellano , descomente la siguiente linea : LANG = es # For english language , uncomment the following line : # LANG = en 59