Library Minim in a Class

edited July 2015 in Library Questions

Hi, If it is possible, I would use Minim in another class, and not in setup(). Is it possible? Because this code say "NullPointerException" at line 29


Music m;
void setup(){
 size(100,100);
 m = new Music();
m.start();
}

void draw(){
}

//============================
//another file where I use Minim 

import ddf.minim.spi.*;
import ddf.minim.signals.*;
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.ugens.*;
import ddf.minim.effects.*;


class Music{

  Minim minim;
  AudioPlayer song;

  Music(){
    minim = new Minim(this);
    song = minim.loadFile("asaf.mp3");
  
  }

  void start(){
    song.play();
  }
  
  void stop(){
     song.close(); 
     minim.stop();
   // super.stop();
  }

}
Tagged:

Answers

  • edited July 2015 Answer ✓

    That could work but Minim needs a PApplet as argument for its constructor, not a Music.

    Music m;
    void setup(){
     size(100,100);
     m = new Music(this);
    m.start();
    }
    
    void draw(){
    }
    
    
    void stop(){
    //Don't forget this!
    m.stop();
    }
    
    //============================
    //another file where I use Minim 
    
    import ddf.minim.spi.*;
    import ddf.minim.signals.*;
    import ddf.minim.*;
    import ddf.minim.analysis.*;
    import ddf.minim.ugens.*;
    import ddf.minim.effects.*;
    
    
    class Music{
    
      Minim minim;
      AudioPlayer song;
    
      Music(PApplet p){
        minim = new Minim(p);
        song = minim.loadFile("asaf.mp3");
    
      }
    
      void start(){
        song.play();
      }
    
      void stop(){
         song.close(); 
         minim.stop();
       // super.stop();
      }
    
    }
    
  • edited July 2015
    • The this inside a class is contextual in Java.
    • For instance, inside class Music, that this means some instance of type Music.
    • Problem is that since it's a Music reference and not PApplet's, it lacks field sketchPath.
    • That's why loadFile() can't find where "asaf.mp3" is unless we specify its full path.
  • A much better sane option is simply pass an already loaded AudioPlayer to Music's constructor. :-\"

  • edited July 2015

    (bad idea)

  • edited July 2015

    It is usual to have a single Minim object. So declare minim globally, create it with new inside setup and pass it to the Music constructor with the music file name.

    The Music class should keep the AudioPlayer field and this would be created in the constructor. This makes sense so that you can control the playback through the Music object.

    It does not make sense to create a loaded AudioPlayer outside the class and pass it to the constructor because you would have to do his for every Music object.

  • @colouredmirrorball thanks! It works now! =D> :)

  • edited July 2015

    It does not make sense to create a loaded AudioPlayer outside the class and pass it to the constructor because you would have to do his for every Music object.

    • @quark, it all makes perfect sense since resources are commonly loaded inside setup().
    • So instead of passing sketch's PApplet reference to Music's constructor: new Music(this);.
    • We pass an AudioPlayer reference instead: new Music(minim.loadFile("asaf.mp3"));.
    • There are many cases in which instances of some class share the very same resource.
    • Thus rather than having those classes loading the resources, we repeat the resource when needed:

    // forum.Processing.org/two/discussion/11559/library-minim-in-a-class
    
    import ddf.minim.Minim;
    import ddf.minim.AudioPlayer;
    
    static final int MUSICS = 3;
    final Music[] musics = new Music[MUSICS];
    
    void setup() {
      size(300, 200, JAVA2D);
      smooth(4);
    
      Minim minim = new Minim(this);
      AudioPlayer song1 = minim.loadFile("asaf.mp3");
      AudioPlayer song2 = minim.loadFile("fasa.mp3");
    
      // musics[0] & musics[2] share the same AudioPlayer resource:
      musics[0] = new Music(song1);
      musics[1] = new Music(song2); // doesn't share resource!
      musics[2] = new Music(song1);
    }
    
    class Music {
      final AudioPlayer song;
    
      Music(AudioPlayer player) {
        (song = player).loop();
      }
    }
    
  • Obviously it depends on what the sketch creator wants but to me ...

    It does not make sense to share AudioPlayer objects between instances of Music because you cannot control individual Music objects. If you stop one and it stops all Music objects that share the AudioPlayer.

    It does not make sense for the Minin instance being a local variable of setup. You might want the user to select the music file at runtime so you would need the minim object to be available outside the setup method.

  • It does not make sense for the Minin instance being a local variable of setup().

    I generally avoid keeping tracking of things that won't be accessed later.
    That's why we use local variables for after all!
    If the need arises later on, it's just as simple as turning the local variable a field. :-\"

  • edited July 2015

    It does not make sense to share AudioPlayer objects between instances of Music because you cannot control individual Music objects.

    Perhaps in his particular sketch there won't be any need to share resources among those Music instances. However it's still good practice to do so nonetheless! L-)

    Let's say we got a sketch w/ some Button instances shown in the canvas.
    And there are some AudioPlayer to be assigned for diff. types of Button.

    Some Button objects needs to play a "confirmation" sound, while others an "error" sound.

    It makes total sense for them to share a particular AudioPlayer sound resource rather than each 1 load the very same file over & over! [-(

  • If the need arises later on, it's just as simple as turning the local variable a field.

    Of course that assumes there is not already a field with the same name :-\"

  • edited July 2015

    Well, of course I've meant that the declaration should go from local scope to global scope! :-@
    But I still need to witness some case where the Minim instance was really needed after setup()! :P

  • Can't make the local declaration global if there is already a field with the same name.

  • edited July 2015

    Can't make the local declaration global if there is already a field with the same name.

    Re-read it: "If the need arises later on, it's just as simple as turning the local variable a field."

    Turning some local variable a field automatically implies removing the local declaration and placing that to the "global" scope! Only its assignment stays "local"! ~O)

  • Perhaps you misunderstood my statement so let me explain in more detail.

    If this code is part of a larger sketch

    String s;  // used throughout class
    
    void setup (){
      int s = 0;
      // here s is an int and is used extensively inside setup
    }
    

    You can't simply promote int s to a field because the identifier has already been used. Would have to change the local variable identifier throughout the setup method before promoting it.

    Although it is good practice to keep variable scope as small as possible it should be done in the context of the program design design.

  • edited July 2015

    You can't simply promote int s to a field because the identifier has already been used.

    • I think you've brought a diff. matter entirely! O_o
    • In my example, I've "demoted" field minim to local variable minim!
    • Simply b/c minim is only accessed inside setup().
    • What I've meant by "when the need arises just turn the local variable to field again", it was simply declare it as field instead of local variable!
    • In all of the cases I've seen about the library Minim, in none of them its reference was necessary outside setup()! (:|
  • edited July 2015

    I have re-read this entire discussion and I stand by my original post. Everything else that follows is waffle.

    It makes sense to have a single instance of Minim because it is accessing the sound hardware resources so we must be certain to release them correctly. Multiple instances of Minim make it difficult to ensure all resources are released. The best way of making minim generally available is to make it a field.

    It makes sense that each Music object has its own AudioPlayer object so that each Music object can be started independently. The example you give showing the AudioPlayer object being shared is a disaster waiting to happen

    musics[0] = new Music(song1);
    musics[1] = new Music(song2); // doesn't share resource!
    musics[2] = new Music(song1);
    

    means that musics [0].stop()also stops musics[2] in fact you would get exactly the same thing if you replaced the last line with

    musics[2] = musics [0];

    A good reason for not sharing AudioPlayer objects.

  • edited July 2015

    From your post I assume you have two tabs (files) so here is my solution to your problem.

    Although it is possible to shorten the code a little there is no need to. Clarity is more important than reducing the code base.

    Main tab:

    import ddf.minim.spi.*;
    import ddf.minim.signals.*;
    import ddf.minim.*;
    import ddf.minim.analysis.*;
    import ddf.minim.ugens.*;
    import ddf.minim.effects.*;
    
    // Make these available throughout the class
    Minim minim;
    Music m;
    
    void setup() {
      size(100, 100);
      // Initialise sound resources
      minim =  new Minim(this);
      // Make the music object
      m = new Music(minim, "asaf.mp3");
      m.start();
    }
    
    void draw() {
    }
    
    // This method is called automatically when the sketch closes
    void stop() {
      //  Stop the music
      m.stop();
      // Release the sound resources
      minim.stop();
      super.stop();
    }
    

    Music.java tab

    //============================
    //another file where I use Minim 
    
    import ddf.minim.spi.*;
    import ddf.minim.signals.*;
    import ddf.minim.*;
    import ddf.minim.analysis.*;
    import ddf.minim.ugens.*;
    import ddf.minim.effects.*;
    
    class Music {
    
      AudioPlayer song;
    
      Music(Minim minim, String fname) {
        song = minim.loadFile(fname);
      }
    
      void start() {
        song.play();
      }
    
      void stop() {
        song.close();
      }
    }
    
  • Thanks for answers @quark and @GoToLoop, It is for a project for university's exam and I do a little animation with music track, but this weeks I didn't have much time, sorry. Anyway thanks again ^:)^

Sign In or Register to comment.