{"id":17,"date":"2007-04-22T02:41:40","date_gmt":"2007-04-22T01:41:40","guid":{"rendered":"http:\/\/slack.codemaniacs.com\/blog\/2007\/04\/22\/sintesis-musical-para-mi-o-para-torpes-en-general-ii\/"},"modified":"2023-05-07T06:44:32","modified_gmt":"2023-05-07T05:44:32","slug":"sintesis-musical-para-mi-o-para-torpes-en-general-ii","status":"publish","type":"post","link":"https:\/\/slack.codemaniacs.com\/blog\/2007\/04\/22\/sintesis-musical-para-mi-o-para-torpes-en-general-ii\/","title":{"rendered":"S\u00edntesis musical para m\u00ed (o para torpes en general :) II"},"content":{"rendered":"<p><strong>2) Senos!!! <\/strong><\/p>\n<p>Despu\u00e9s del ruido del capitulo anterior, vamos a pasar a algo ligeramente m\u00e1s interesante: la <a href=\"http:\/\/en.wikipedia.org\/wiki\/Sine_wave\">onda senoidal<\/a>. Como pod\u00e9is ver si segu\u00eds el enlace a la pagina sobre la onda senoidal en la wikipedia, junto con dibujitos y explicaciones interesantes, la formula es:<\/p>\n<blockquote><p><em>y<\/em> = <em>A<\/em>\u00b7sin(<em>w\u00b7t<\/em> + <em>fase<\/em>)<\/p><\/blockquote>\n<p>donde <em>A<\/em> es la amplitud de la onda (la distancia entre una cresta y un valle), <em>w<\/em> es la frecuencia en radianes\/segundo y <em>t<\/em> es el tiempo. Vamos a ignorar la fase porque no nos hace falta :)<\/p>\n<p>Como nos gusta trabajar con frecuencias en hercios, multiplicamos por 2\u00b7pi. Adem\u00e1s, tenemos que t = samples generados \/ frecuencia de muestreo. Por lo tanto en el c\u00f3digo tendremos algo como:<\/p>\n<blockquote><p>y[i] = A*sin(2*pi*frecuencia*(i\/sampling_rate))<\/p><\/blockquote>\n<p>para el sample i-\u00e9simo desde el inicio del sonido. Vamos a ver el trozo de c\u00f3digo correspondiente (lo que falta es, b\u00e1sicamente, la inicializaci\u00f3n del cap\u00edtulo anterior):<\/p>\n<pre>void play(void *userdata, Uint8 *stream, int len)\n{\n    int num_samples = len \/ 2;\n    Sint16 *dst_buf = (Sint16*) stream;\n    for (int i=0; i&lt;num_samples ; ++i)\n        buffer[i] = sin(2.0*M_PI*440.0f*(i+pos)\/(float)SAMPLING_RATE);\n    \n    \/\/ Clipping y conversion a Sint16\n    for (int i=0; i&lt;num_samples; ++i)\n    {\n        float v = buffer[i];\n        if (v &gt; 1.0f)\n            v = 1.0f;\n        else if (v&lt; -1.0f)\n            v = -1.0f;\n\n        dst_buf[i] = (Sint16)(32767.0f*v);\n    }\n    pos += num_samples;\n\n}\n<\/pre>\n<p>Detalles destacables de esta funci\u00f3n:<\/p>\n<ul>\n<li>se trabaja con un buffer de floats y se convierte a entero al final. No mola ir perdiendo precisi\u00f3n por el camino, sobre todo cuando hagamos cosas mas complejas<\/li>\n<li>hay clipping a [-1.0, 1.0]. Ahora mismo es completamente innecesario porque sin() devuelve valores en ese intervalo, pero cuando empecemos a mezclar varios sonidos vendr\u00e1 bien :)<\/li>\n<li>en la llamada a sin(), el 440.0f es la <a href=\"http:\/\/en.wikipedia.org\/wiki\/Piano_key_frequencies\">frecuencia<\/a> de la nota que suena (un <a href=\"http:\/\/en.wikipedia.org\/wiki\/A440\">La4<\/a>), y pos es una variable global que guarda el \u00ed\u00adndice del ultimo sample generado entre llamadas a play(). Es feo, pero para un ejemplo peque\u00f1o va bien.<\/li>\n<\/ul>\n<p>En el pr\u00f3ximo episodio (ahora es tarde y tengo sue\u00f1o), veremos otros osciladores t\u00edpicos y cosas interesantes que se pueden hacer con ellos.<\/p>\n<p><b>EDIT:<\/b> <a href=\"http:\/\/herotyc.com\/\">herotyc<\/a> me ha enviado una <a href=\"http:\/\/slack.codemaniacs.com\/misc\/tutorial_sintesis\/sintesis02_senos.c\">versi\u00f3n stand-alone del ejemplo<\/a> de este cap\u00edtulo. \u00a1Muchas gracias! :)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>2) Senos!!! Despu\u00e9s del ruido del capitulo anterior, vamos a pasar a algo ligeramente m\u00e1s interesante: la onda senoidal. Como pod\u00e9is ver si segu\u00eds el enlace a la pagina sobre la onda senoidal en la wikipedia, junto con dibujitos y explicaciones interesantes, la formula es: y = A\u00b7sin(w\u00b7t + fase) donde A es la amplitud [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[2,4,6,3],"tags":[],"_links":{"self":[{"href":"https:\/\/slack.codemaniacs.com\/blog\/wp-json\/wp\/v2\/posts\/17"}],"collection":[{"href":"https:\/\/slack.codemaniacs.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/slack.codemaniacs.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/slack.codemaniacs.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/slack.codemaniacs.com\/blog\/wp-json\/wp\/v2\/comments?post=17"}],"version-history":[{"count":2,"href":"https:\/\/slack.codemaniacs.com\/blog\/wp-json\/wp\/v2\/posts\/17\/revisions"}],"predecessor-version":[{"id":99,"href":"https:\/\/slack.codemaniacs.com\/blog\/wp-json\/wp\/v2\/posts\/17\/revisions\/99"}],"wp:attachment":[{"href":"https:\/\/slack.codemaniacs.com\/blog\/wp-json\/wp\/v2\/media?parent=17"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/slack.codemaniacs.com\/blog\/wp-json\/wp\/v2\/categories?post=17"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/slack.codemaniacs.com\/blog\/wp-json\/wp\/v2\/tags?post=17"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}