<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Hello World: &#187; Advanced Sound Library</title>
	<atom:link href="http://razorblade.netsons.org/tag/advanced-sound-library/feed/" rel="self" type="application/rss+xml" />
	<link>http://razorblade.netsons.org</link>
	<description>Programmazione web e oltre: php5, Zend Framework, jQuery, Actionscript 3.0, Sandy 3D Engine e altro</description>
	<lastBuildDate>Fri, 28 Aug 2009 18:23:41 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Homebrew Nintendo DS: gestione dell&#8217;audio con Advanced Sound Library e PALib</title>
		<link>http://razorblade.netsons.org/2008/11/18/homebrew-nintendo-ds-gestione-dellaudio-con-advanced-sound-library-e-palib/</link>
		<comments>http://razorblade.netsons.org/2008/11/18/homebrew-nintendo-ds-gestione-dellaudio-con-advanced-sound-library-e-palib/#comments</comments>
		<pubDate>Tue, 18 Nov 2008 20:02:24 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Nintendo DS]]></category>
		<category><![CDATA[homebrew]]></category>
		<category><![CDATA[Advanced Sound Library]]></category>
		<category><![CDATA[AS_MP3StreamPlay]]></category>
		<category><![CDATA[DevKitPro]]></category>
		<category><![CDATA[nintendo DS]]></category>
		<category><![CDATA[PALib]]></category>
		<category><![CDATA[total audio converter]]></category>

		<guid isPermaLink="false">http://razorblade.netsons.org/?p=54</guid>
		<description><![CDATA[<h2>Riprodurre file audio con il Nintendo DS</h2>
<p>In questo secondo articolo sul portatile di casa Nintendo vedremo come riprodurre i file audio utilizzando le Advanced Sound Libraries. Premetto che si tratteranno di file audio precompilati, ovvero sceglieremo a priori quali files riprodurre ed il programma potrà riprodurre solo quelli. Ma vedremo presto ( spero..) qualcosa di più avanzato unendo il codice qui di seguito con la gestione del file system.</p>

<p>Vedremo ora come riprodurre due tipi di files, mp3 e raw, i primi utilizzati per riprodurre veri e propri brani, i secondi per riprodurre brevi effetti sonori. Inoltre vedremo anche come far riprodurre al Nintendo DS delle note senza la necessità di files audio esterni.</p>

<p>Una nota importante prima di cominciare riguarda<a href="http://razorblade.netsons.org/2008/11/18/homebrew-nintendo-ds-gestione-dellaudio-con-advanced-sound-library-e-palib/">[...] Continua</a></p>


No related posts.

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<h2>Riprodurre file audio con il Nintendo DS</h2>
<p>In questo secondo articolo sul portatile di casa Nintendo vedremo come riprodurre i file audio utilizzando le Advanced Sound Libraries. Premetto che si tratteranno di file audio precompilati, ovvero sceglieremo a priori quali files riprodurre ed il programma potrà riprodurre solo quelli. Ma vedremo presto ( spero..) qualcosa di più avanzato unendo il codice qui di seguito con la gestione del file system.</p>
<p>Vedremo ora come riprodurre due tipi di files, mp3 e raw, i primi utilizzati per riprodurre veri e propri brani, i secondi per riprodurre brevi effetti sonori. Inoltre vedremo anche come far riprodurre al Nintendo DS delle note senza la necessità di files audio esterni.</p>
<p>Una nota importante prima di cominciare riguarda la locazione dei file audio: questi devono essere all&#8217;interno della cartella <b>data</b> del template del progetto. Se la cartella non esiste createla. Inoltre da porre particolare attenzione alle caratteristiche dei file MP3: questi devono essere 8bit, samplerate massimo 32000 Hz, 80 kbps massimo. Alcuni di questi limiti possono essere sorpassati ma non vi è la necessità. Altri invece possono causare il non funzionamento dell&#8217;audio. Potete trovare al termine dell&#8217;articolo una breve nota riguardo la conversione di un mp3 per poterlo utilizzare senza problemi. Infine la dimensione totale dei file audio non deve superare i 4MB, in quanto occuperebbero totalmente la dimensione della ram del Nintendo DS.</p>
<p>Organizzeremo questa breve applicazione in 3 modalità, MP3,SFX,PSG, switchabili tramite la pressione della croce direzionale destra e sinistra.</p>
<p>Siccome il listato completo è piuttosto lungo, inserirò il codice man mano che procederò con le spiegazioni.</p>
<h2>Inclusioni e inizializzazione variabili</h2>
<p>In questa prima porzione includiamo le librerie ed inizializziamo le variabili. Non mi dilungherò su cosa è una struct, per questo argomento vi consiglio di cercarvi un manuale di C o una guida su internet. Successivamente alla struct abbiamo l&#8217;inizializzazione delle funzioni che compongono questa applicazione. Queste sono incluse nel file dopo la main class, quindi abbiamo la necessità di dichiararle prima.</p>
<pre name="code" class="php">
  #include &lt;nds.h&gt;
  #include &lt;pa9.h&gt;
  //#include &lt;fat.h&gt;

  // Il file MP3
  #include "milk.h"

  // I files RAW
  #include "sfxa.h"
  #include "sfxb.h"	

  // Struct comprendente le variabili
  typedef struct{
		int rate, newrate, modalita;
    bool autopan;
    u8 lastsfx, duty, pan, fx_mode, usage;
    s32 note;
    char next[4];
    char prev[4];
    char actl[4];
	} AudioData;

  // Inizializzazione funzioni
  void SwitchMode(AudioData * AData);
  void ModeMp3(AudioData * AData);
  void ModeSfx(AudioData * AData);
  void ModePsg(AudioData * AData);
  void RemoveSound(AudioData * AData);
</pre>
<h2>La main class dell&#8217;applicazione</h2>
<p>La seguente porzione di codice include la main class dell&#8217;applicazione. Questa si occupa di inizializzare PALib, Inizializzare ASLib, definire le modalità disponibili, istanziare la struct ed attribuire dei valori iniziali alle sue proprietà, creare il ciclo dell&#8217;applicazione.</p>
<p>Nel ciclo dell&#8217;applicazione, oltre che inizializzare la visualizzazione di alcune stringhe di testo, inseriamo uno switch sul valore della proprietà <b>modalita</b>: questa viene modificata alla pressione della croce direzionale ( dx e sx ), all&#8217;interno della funzion SwitchMode.</p>
<p>In base alla modalità sarà richiamata la funzione relativa alla modalità richiesta.</p>
<pre name="code" class="php">
  int main(int argc, char** argv)
  {
    // Inizializzazione PALib
    PA_Init();
    PA_InitVBL();
    PA_InitText(0, 0);
    PA_InitText(1, 0);

    // Inizializzazione ASLib
    PA_VBLFunctionInit(AS_SoundVBL);
    AS_Init(AS_MODE_MP3 | AS_MODE_SURROUND | AS_MODE_16CH);
    AS_SetDefaultSettings(AS_PCM_8BIT, 11050, AS_SURROUND);

    // Le modalità disponibili
    #define MODALITA_MP3 0
    #define MODALITA_SFX 1
    #define MODALITA_PSG 2

    AudioData Audio;

    // Valori per le proprietà della struct
    Audio.rate = 0;
    Audio.newrate = 0;
    Audio.modalita = MODALITA_MP3;
    Audio.autopan = false;
    Audio.lastsfx = 0;
    Audio.pan = 0;
    Audio.usage = 0;
    Audio.fx_mode = AS_SURROUND;
    strcpy(Audio.next,"SFX");
    strcpy(Audio.prev,"PSG");
    strcpy(Audio.actl,"MP3");    

    // Ciclo dell'applicazione
    while (1){
      // Schermo superiore
      PA_OutputText(1, 0, 3,  "  Esempio ASLib by Razorblade\n");
      PA_OutputText(1, 0, 5,  "       PadLeft e PadRight/n/n"
                              "     per cambiare modalità\n");

      PA_OutputText(1, 0, 20, "  Le modalità sono MP3,SFX,PSG \n");

      // Schermo Inferiore
      PA_OutputText(0, 0, 2,  " http://razorblade.netsons.org\n");

      switch(Audio.modalita){
        // Modalità Mp3
        case MODALITA_MP3: ModeMp3(&#038;Audio); break;
        // Modalità Sfx
        case MODALITA_SFX: ModeSfx(&#038;Audio); break;
        // Modalità Psg
        case MODALITA_PSG: ModePsg(&#038;Audio); break;
      }

      SwitchMode(&#038;Audio);

      // Comando per lo switch
      PA_OutputText(1, 0, 22, "PREV: %s  || %s ||  NEXT: %s\n", Audio.prev, Audio.actl, Audio.next);

      // Sincronizzazione
      PA_WaitForVBL();
    }
    return 0;
  }
</pre>
<h2>Le funzioni SwitchMode e RemoveSound</h2>
<p>Si occupa di modificare le modalità la funzione SwitchMode, qui di seguito il suo codice che non merita particolari spiegazioni. La funzione RemoveSound è un helper che rimuove suoni in riproduzione ( se ce ne sono ) al cambio di modalità</p>
<pre name="code" class="php">

	//
  //  SwitchMode
  //  Passa alla modalità successiva
  //

  void SwitchMode(AudioData * AData){
    bool clearScreen = false;

    switch(AData->modalita){
      case MODALITA_MP3:
        strcpy(AData->prev,"PSG");
        strcpy(AData->next,"SFX");
        strcpy(AData->actl,"MP3");
      break;
      case MODALITA_SFX:
        strcpy(AData->prev,"MP3");
        strcpy(AData->next,"PSG");
        strcpy(AData->actl,"SFX");
      break;
      case MODALITA_PSG:
        strcpy(AData->prev,"SFX");
        strcpy(AData->next,"MP3");
        strcpy(AData->actl,"PSG");
      break;
    }

    if ((Pad.Newpress.Right)){
      clearScreen = true;
      RemoveSound(AData);
      AData->modalita = AData->modalita == MODALITA_PSG ? MODALITA_MP3 : (AData->modalita+1);
    }
    if ((Pad.Newpress.Left)) {
      clearScreen = true;
      RemoveSound(AData);
      AData->modalita = AData->modalita == MODALITA_MP3 ? MODALITA_PSG : (AData->modalita-1);
    }
    if(clearScreen){
    	// Rimuoviamo tutti i tasti dallo schermo superiore
    	PA_ClearTextBg(0);
    	PA_ClearTextBg(1);
    }
  }

	//
  //  RemoveSound
  //  Rimuove i suoni inizializzati
  //

  void RemoveSound(AudioData * AData){
    switch(AData->modalita){
      case MODALITA_MP3:
        AS_MP3Stop();
      break;
      case MODALITA_SFX:
      break;
      case MODALITA_PSG:
        PA_PlayPSG(8, 0, 0, 0, 0);
        PA_PlayPSG(9, 0, 0, 0, 0);
      break;
    }
  }
</pre>
<h2>La modalita MP3</h2>
<p>Qui di seguito il codice della funzione che gestisce la modalità mp3. Nella blocco successivo al commento &#8216;controlli&#8217; potete vedere le funzionalità che servono effettivamente a controllare la riproduzione del file audio. In questa modalità potete usare la <b>Stylus</b> per modificare in tempo reale il sample rate. Se per caso vi viene in mente di modificare il calcolo del nuovo samplerate al movimento della stylus fate solo attenzione perchè superando certi limiti sia l&#8217;emulatore che la console Nintendo DS crashano ( il calcolo attuale modifica il samplerate al limite gestibile ).</p>
<pre name="code" class="php">
	//
  //  ModeMp3
  //  Gestisce la modalità MP3
  //

  void ModeMp3(AudioData * AData){
    // Mostriamo i comandi su schermo
    PA_OutputText(1, 0, 9,  "   A: play MP3   B: pause MP3\n\n"
                            "X: stop MP3   Y: surround ON/OFF\n\n"
                            "  Stylus : <> pan   ^ v pitch\n\n" );

    // Visualizzazione Sample Rate e Pan
    PA_OutputText(1, 0, 14, " Sample rate : %d   pan : %d  \n", AData->newrate, IPC_Sound->chan[IPC_Sound->mp3.channelL].snd.pan);

    // show surround status
    PA_OutputText(1, 0, 16, "          Surround : %s\n", (IPC_Sound->mp3.delay ? "ON " : "OFF"));
    PA_OutputText(1, 0, 17, "  ( stop e play per applicare )");

    // show playback status
    PA_OutputText(0, 0, 19, "     MP3 Status : ");
    switch (AS_GetMP3Status()) {
      case (MP3ST_STOPPED)      : PA_OutputText(0, 18, 19, "stopped         "); break;
      case (MP3ST_PAUSED)       : PA_OutputText(0, 18, 19, "paused          "); break;
      case (MP3ST_PLAYING)      : PA_OutputText(0, 18, 19, "playing         "); break;
      case (MP3ST_OUT_OF_DATA)  : PA_OutputText(0, 18, 19, "out of data     "); break;
      case (MP3ST_DECODE_ERROR) : PA_OutputText(0, 18, 19, "decoding error  "); break;
      case (MP3ST_INITFAILED)   : PA_OutputText(0, 18, 19, "init failed     "); break;
    }

    // I Controlli
    if (Pad.Newpress.A){
      if (AS_GetMP3Status() &#038; MP3ST_PAUSED) {
        AS_MP3Unpause();
      }else{
        AS_MP3StreamPlay("milk.mp3");
        AS_MP3DirectPlay((u8*)milk, (u32)milk_size);
        AS_SetMP3Loop(true);
        AData->rate = 0;
        AData->newrate = 0;
      }
    }
    if (Pad.Newpress.B){
      AS_MP3Pause();
    }
    if (Pad.Newpress.X){
      AS_MP3Stop();
    }
    if (Pad.Newpress.Y){
      if(IPC_Sound->mp3.delay){
        AS_SetMP3Delay(AS_NO_DELAY);
      }else{
        AS_SetMP3Delay(AS_SURROUND);
      }
    }
    if((Stylus.Held) &#038;&#038; AData->rate &#038;&#038; (AS_GetMP3Status() &#038; MP3ST_PLAYING)){
      //AData->newrate = (AData->rate + AData->rate/4) - (AData->rate * Stylus.Y / 96 / 4);
      AData->newrate = AData->rate + ((190 - Stylus.Y - 95) * 150);
      AS_SetMP3Rate(AData->newrate);
      AS_SetMP3Pan(Stylus.X / 2);
    }

    // Nuovo Sample Rate
    if(AData->rate == 0 &#038;&#038; IPC_Sound->mp3.rate &#038;&#038; (AS_GetMP3Status() &#038; MP3ST_PLAYING)) {
      AData->rate = IPC_Sound->mp3.rate;
      AData->newrate = AData->rate;
    }
  }
</pre>
<h2>La modalita SFX</h2>
<p>La modalità SFX si occupa di riprodurre i file .raw. In questa modalità includiamo il conteggio dei canali audio impegnati.</p>
<pre name="code" class="php">
	//
  //  ModeSfx
  //  Gestisce la modalità SFX
  //

  void ModeSfx(AudioData * AData){
    // Mostriamo i comandi su schermo
    PA_OutputText(1, 0, 9,  "   A: play SFXA  B: play SFXB \n\n"
                            "  X: autopan ON/OFF Y: FX mode\n" );

    // Visualizza l'utilizzo dei canali, lo stato dell'autopan e l'ultimo suono avviato
    PA_OutputText(1, 0, 13, "      Canali Usati : %d / %d  \n\n", AData->usage, IPC_Sound->num_chan - 1);
    PA_OutputText(1, 0, 15, "        Autopan : %s\n\n", (AData->autopan ? "on " : "off"));
    PA_OutputText(1, 0, 17, "       Last SFX pan : %d  \n", IPC_Sound->chan[AData->lastsfx].snd.pan);

    // Visualizza Modalità FX
    PA_OutputText(1, 0, 19, "     Effetto SFX : %s\n", (AData->fx_mode == AS_SURROUND ? "surround" : ( AData->fx_mode == AS_REVERB ? "reverb  " : "no fx   ")));
    PA_OutputText(1, 0, 20, " ( riavvia SFX per applicare )");

    // I Controlli
    if (Pad.Newpress.A) {
      AData->lastsfx = AS_SoundQuickPlay(sfxa); // Ritorna il canale audio in modo da potergli applicare degli effetti come pan, volume ecc..
    }
    if (Pad.Newpress.B) {
      AData->lastsfx = AS_SoundQuickPlay(sfxb); // Ritorna il canale audio in modo da potergli applicare degli effetti come pan, volume ecc..
    }
    if (Pad.Newpress.X) {
      AData->autopan = !AData->autopan;
    }
    if (Pad.Newpress.Y) {
      if(AData->fx_mode == AS_SURROUND){
        AData->fx_mode = AS_REVERB;
      } else if(AData->fx_mode == AS_REVERB){
        AData->fx_mode = AS_NO_DELAY;
      } else {
        AData->fx_mode = AS_SURROUND;
      }
      // set new default sound settings
      AS_SetDefaultSettings(AS_PCM_8BIT, 11025, AData->fx_mode);
    }      

    // Autopan
    if(AData->autopan){
      AS_SetSoundPan(AData->lastsfx, (++AData->pan > 127 ? 255 - AData->pan : AData->pan));
    }            

    // get the number of busy channels
    AData->usage = 0;
    u8 i;
    for(i = 1; i < IPC_Sound->num_chan; i++){
      if(IPC_Sound->chan[i].busy){
        AData->usage = (AData->usage+1);
      }
    }
  }
</pre>
<h2>La modalita PSG</h2>
<p>La modalità PSG si occupa di far riprodurre delle note al Nintendo DS senza la necessità di utilizzare files esterni. Per riprodurre le note possiamo utilizzare la stylus, ed ovviamente cambia la nota al cambiare della posizione</p>
<pre name="code" class="php">

	//
  //  ModePsg
  //  Gestisce la modalità PSG
  //

  void ModePsg(AudioData * AData){
    int C_scale[8] = {33,37,41,44,49,55,62,65}; // Scale for notes in C major scale
    AData->pan = 64;
    PA_OutputText(1, 0, 9,"Usa il pennino per cambiare nota");
    PA_OutputText(1, 0, 12, "     Canali Usati : %d / %d  \n\n", AData->usage, IPC_Sound->num_chan - 1);
		AData->note = C_scale[(Stylus.X>>5)]< &lt;4;
		//pan = (Stylus.Y*0.66);
		AData->pan += Pad.Held.Right-Pad.Held.Left; // Change pan with pad
		AData->duty = Stylus.Y/24; // 0-7

		// Check the stylus presses :
		if (Stylus.Held){
      PA_PlayPSG(8, 127, AData->pan, AData->note, AData->duty);
      PA_PlayPSG(9, 127, AData->pan, AData->note*2, AData->duty);//octave
    }else{
      PA_PlayPSG(8, 0, 0, 0, 0);  // Blank sound
      PA_PlayPSG(9, 0, 0, 0, 0);  // Blank sound
    }	

		// Get the stylus position and show it on screen
		PA_OutputText(1, 0, 15, "Coordinate Pennino XY : %d, %d   ", Stylus.X, Stylus.Y);
		PA_OutputText(1, 0, 17, " Nota : %d  Pan : %d  Duty : %d    ", AData->note, AData->pan, AData->duty);	          

    // get the number of busy channels
    AData->usage = 0;
    u8 i;
    for(i = 1; i < IPC_Sound->num_chan; i++){
      if(IPC_Sound->chan[i].busy){
        AData->usage = (AData->usage+1);
      }
    }
  }
</pre>
<p> Tutti i codici che abbiamo visto sono delle versioni rivedute dei codici contenuti negli esempi di PALib. Per ulteriori info vi rimando al <a href="http://palib.info/Doc/PAlibDoc%20Eng/modules.html">sito ufficiale</a>.</p>
<h2>Nota sulla conversione dei files MP3</h2>
<p>Mi è capitato di avere dei problemi a far funzionare a dovere i files MP3. Se anche i vostri mp3 non ne vogliono sapere di funzionare provate ad utilizzare il programma <a href="http://www.coolutils.com/TotalAudioConverter">Total Audio Converter</a>, uno dei più completi programmi per la conversione di files audio. Tramite questo programma ho dovuto seguire 2 passaggi per far funzionare l&#8217;mp3 finale:</p>
<ul class="listato">
<li> Conversione dell&#8217;mp3 in .wav 8bit</li>
<li> Conversione del wav risultante in mp3 32000Hz 80Kbps</li>
</ul>
<p>Potete scaricare un archivio rar contenente l&#8217;intero template del progetto <a href="http://razorblade.netsons.org/files/nds/sound.rar">cliccando qui</a>.</p>
<p>Termina qui questo tutorial sulla riproduzione dei file audio con il Nintendo DS e le PALib/ASLib, commentate e votate.</p>
<div class="ratings">Note: There is a rating embedded within this post, please visit this post to rate it.</div>


<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://razorblade.netsons.org/2008/11/18/homebrew-nintendo-ds-gestione-dellaudio-con-advanced-sound-library-e-palib/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
