Playback of MOD (tracker) files

  ... the .MOD Player Extension for AndEngine.

Re: Playback of MOD (tracker) files

Postby Shadaez » Sat Aug 14, 2010 12:58 pm

Using
import java.util.concurrent.Callable;
instead of AndEngine's fixed it.
Shadaez
 
Posts: 15
Joined: Sat Aug 14, 2010 7:12 am

Re: Playback of MOD (tracker) files

Postby alex » Thu Aug 26, 2010 8:19 am

Shadaez, did you find a solution to the looping problem? i.e. the mod player doesn't loop music

the xmp android project hasn't been updated in 3 months... so depressing :cry:
http://xmp.git.sourceforge.net/git/gitweb.cgi?p=xmp/xmp;a=history;f=src/android/project;hb=HEAD
alex
 
Posts: 275
Joined: Thu Jul 01, 2010 8:21 pm

Re: Playback of MOD (tracker) files

Postby oldskool73 » Mon Nov 29, 2010 10:52 am

I just noticed that there seems to have been a flurry of activity on this project over the last 6 weeks on SourceForge, might be worth pulling the latest updates into the jar?
http://xmp.git.sourceforge.net/git/gitw ... ;a=summary

Also, I'm not sure but I think we need access to the ModInfo class to get the tune length etc, can't do that with the current version. (Xmp.getModInfo() gives an error : 'The type ModInfo is not visible')

Makes it a bit un-useable as there's currently no way to tell when the track has stopped to loop it or play another tune etc.
oldskool73
 
Posts: 128
Joined: Tue Oct 12, 2010 4:04 pm

Re: Playback of MOD (tracker) files

Postby alex » Tue Nov 30, 2010 12:38 am

yeah I sent Nicolas a PM about it a couple of days ago
alex
 
Posts: 275
Joined: Thu Jul 01, 2010 8:21 pm

Re: Playback of MOD (tracker) files

Postby kawaiimomo » Thu Oct 27, 2011 8:29 pm

I modified the ModPlayer.java to do looping of the mods. If anyone interested (added stopRequested), the loop can be better written :-P

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. public boolean stopRequested;
  2.         private class PlayRunnable implements Runnable {
  3.         public void run() {
  4.                 stopRequested = false;
  5.                 short buffer[] = new short[minSize];
  6.                 int result = xmp.playFrame();
  7.                 while (result == 0  && !stopRequested) {
  8.                         int size = xmp.softmixer();
  9.                         buffer = xmp.getBuffer(size, buffer);
  10.                         audio.write(buffer, 0, size / 2);
  11.                        
  12.                         while (paused) {
  13.                                 try {
  14.                                                 Thread.sleep(500);
  15.                                         } catch (InterruptedException e) {
  16.                                                 break;
  17.                                         }
  18.                         }
  19.                         result = xmp.playFrame();
  20.                         if (result != 0) {
  21.                                 xmp.seek(0L);
  22.                                 result = xmp.playFrame();
  23.                         }
  24.                 }
  25.                
  26.                 audio.stop();
  27.                 xmp.endPlayer();
  28.                 xmp.releaseModule();
  29.         }
  30.     }
  31.    
  32.     public void stop() {
  33.         xmp.stopModule();
  34.         paused = false;
  35.         stopRequested = true;
  36.     }
Parsed in 0.012 seconds, using GeSHi 1.0.8.4
kawaiimomo
 
Posts: 12
Joined: Mon Oct 24, 2011 3:50 pm

Re: Playback of MOD (tracker) files

Postby alex » Mon Dec 24, 2012 2:01 am

thanks for posting that looping code. I was comparing it to how HellLabs does it in
\xmp\players\android\src\org\helllabs\android\xmp\ModService.java
and it's the same loop idea.


See below the relevant code (specifically, starting at line 73) from ModService.java :

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.         private class PlayRunnable implements Runnable {
  2.         public void run() {
  3.                 returnToPrev = false;
  4.                 do {                           
  5.                         fileName = queue.getFilename();         // Used in reconnection
  6.                        
  7.                         if (!InfoCache.testModule(fileName)) {
  8.                                 Log.w("Xmp ModService", fileName + ": unrecognized format");
  9.                                 if (returnToPrev)
  10.                                         queue.previous();
  11.                                 continue;
  12.                         }
  13.                        
  14.                         Log.i("Xmp ModService", "Load " + fileName);
  15.                         if (xmp.loadModule(fileName) < 0) {
  16.                                 Log.e("Xmp ModService", "Error loading " + fileName);
  17.                                 if (returnToPrev)
  18.                                         queue.previous();
  19.                                 continue;
  20.                         }
  21.                        
  22.                         returnToPrev = false;
  23.  
  24.                         notifier.notification(xmp.getModName(), queue.index());
  25.                         isLoaded = true;
  26.                        
  27.                         // Unmute all channels
  28.                         for (int i = 0; i < 64; i++) {
  29.                                 xmp.mute(i, 0);
  30.                         }
  31.                                        
  32.                         int numClients = callbacks.beginBroadcast();
  33.                         for (int j = 0; j < numClients; j++) {
  34.                                 try {
  35.                                         callbacks.getBroadcastItem(j).newModCallback(
  36.                                                                 fileName, xmp.getInstruments());
  37.                                 } catch (RemoteException e) { }
  38.                         }
  39.                         callbacks.finishBroadcast();
  40.  
  41.                         String volBoost = prefs.getString(Settings.PREF_VOL_BOOST, "1");
  42.                        
  43.                         final int[] interpTypes = { Xmp.XMP_INTERP_NEAREST, Xmp.XMP_INTERP_LINEAR, Xmp.XMP_INTERP_SPLINE };
  44.                         final int temp = Integer.parseInt(prefs.getString(Settings.PREF_INTERP_TYPE, "1"));
  45.                         int interpType;
  46.                         if (temp >= 1 && temp <= 2) {
  47.                                 interpType = interpTypes[temp];
  48.                         } else {
  49.                                 interpType = Xmp.XMP_INTERP_LINEAR;
  50.                         }
  51.                        
  52.                         int dsp = 0;
  53.                         if (prefs.getBoolean(Settings.PREF_FILTER, true)) {
  54.                                 dsp |= Xmp.XMP_DSP_LOWPASS;
  55.                         }
  56.                        
  57.                         if (!prefs.getBoolean(Settings.PREF_INTERPOLATE, true)) {
  58.                                 interpType = Xmp.XMP_INTERP_NEAREST;
  59.                         }
  60.  
  61.                         audio.play();
  62.                         xmp.startPlayer(0, sampleRate, sampleFormat);
  63.                         xmp.setMixer(Xmp.XMP_MIXER_AMP, Integer.parseInt(volBoost));
  64.                         xmp.setMixer(Xmp.XMP_MIXER_MIX, prefs.getInt(Settings.PREF_PAN_SEPARATION, 70));
  65.                         xmp.setMixer(Xmp.XMP_MIXER_INTERP, interpType);
  66.                         xmp.setMixer(Xmp.XMP_MIXER_DSP, dsp);
  67.                                                
  68.                         updateData = true;
  69.                                                
  70.                         short buffer[] = new short[bufferSize];
  71.                        
  72.                         int count, loopCount = 0;
  73.                         while (xmp.playFrame() == 0) {
  74.                                 count = xmp.getLoopCount();
  75.                                 if (!looped && count != loopCount)
  76.                                         break;
  77.                                 loopCount = count;
  78.                                
  79.                                 int size = xmp.getBuffer(buffer);
  80.                                 audio.write(buffer, 0, size);
  81.                                
  82.                                 while (paused) {
  83.                                         audio.pause();
  84.                                         watchdog.refresh();
  85.                                         try {
  86.                                                         Thread.sleep(500);
  87.                                                         checkMediaButtons();
  88.                                                 } catch (InterruptedException e) {
  89.                                                         break;
  90.                                                 }
  91.                                 }
  92.                                 audio.play();
  93.                                
  94.                                 watchdog.refresh();
  95.                                 checkMediaButtons();
  96.                         }
  97.  
  98.                         xmp.endPlayer();
  99.                        
  100.                         isLoaded = false;
  101.                        
  102.                         numClients = callbacks.beginBroadcast();
  103.                         for (int j = 0; j < numClients; j++) {
  104.                                 try {
  105.                                         callbacks.getBroadcastItem(j).endModCallback();
  106.                                 } catch (RemoteException e) { }
  107.                         }
  108.                         callbacks.finishBroadcast();
  109.                        
  110.                         xmp.releaseModule();
  111.                
  112.                         audio.stop();
  113.                        
  114.                         if (restartList) {
  115.                                 //queue.restart();
  116.                                 queue.setIndex(startIndex - 1);
  117.                                 restartList = false;
  118.                                 continue;
  119.                         }
  120.                        
  121.                         if (returnToPrev) {
  122.                                 queue.previous();
  123.                                 //returnToPrev = false;
  124.                                 continue;
  125.                         }
  126.                 } while (!stopPlaying && queue.next());
  127.  
  128.                 synchronized (updateData) {
  129.                         updateData = false;             // stop getChannelData update
  130.                 }
  131.                 watchdog.stop();
  132.                 notifier.cancel();
  133.                 end();
  134.                 stopSelf();
  135.         }
  136.     }
  137.  
  138.         protected void end() {         
  139.                 Log.i("Xmp ModService", "End service");
  140.             final int numClients = callbacks.beginBroadcast();
  141.             for (int i = 0; i < numClients; i++) {
  142.                 try {
  143.                                 callbacks.getBroadcastItem(i).endPlayCallback();
  144.                         } catch (RemoteException e) { }
  145.             }      
  146.             callbacks.finishBroadcast();
  147.  
  148.             isAlive = false;
  149.         xmp.stopModule();
  150.         paused = false;
  151.  
  152.         /*if (playThread != null && playThread.isAlive()) {
  153.                 try {
  154.                         playThread.join();
  155.                 } catch (InterruptedException e) { }
  156.         }*/
  157.        
  158.         xmp.deinit();
  159.         audio.release();
  160.     }
Parsed in 0.018 seconds, using GeSHi 1.0.8.4
alex
 
Posts: 275
Joined: Thu Jul 01, 2010 8:21 pm

Re: Playback of MOD (tracker) files

Postby alex » Mon Dec 24, 2012 6:42 am

This is how I implemented the looping, including the updates to the deprecated Android constants (which XMP is still using to this day!):

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. package org.helllabs.android.xmp;
  2.  
  3. import android.media.AudioFormat;
  4. import android.media.AudioManager;
  5. import android.media.AudioTrack;
  6.  
  7.  
  8. public class ModPlayer {
  9.         private boolean mStopModule = false;
  10.         private static ModPlayer instance = null;
  11.         private Xmp xmp = new Xmp();
  12.         private int minSize = AudioTrack.getMinBufferSize(44100,
  13.                         AudioFormat.CHANNEL_OUT_STEREO,
  14.                         AudioFormat.ENCODING_PCM_16BIT);
  15.         private AudioTrack audio = new AudioTrack(
  16.                         AudioManager.STREAM_MUSIC, 44100,
  17.                         AudioFormat.CHANNEL_OUT_STEREO,
  18.                         AudioFormat.ENCODING_PCM_16BIT,
  19.                         minSize < 4096 ? 4096 : minSize,
  20.                         AudioTrack.MODE_STREAM);
  21.         protected boolean paused;
  22.         private Thread playThread;
  23.        
  24.         protected ModPlayer() {
  25.               // empty
  26.         }
  27.        
  28.         public static ModPlayer getInstance() {
  29.                 if(instance == null) {
  30.                         instance = new ModPlayer();
  31.                         instance.xmp.init();
  32.                         instance.paused = false;
  33.                 }
  34.                 return instance;
  35.         }
  36.            
  37.         private class PlayRunnable implements Runnable {
  38.                
  39.                 public boolean loopForever = false;
  40.                
  41.                 public PlayRunnable(boolean bValue)
  42.                 {
  43.                         loopForever=bValue;
  44.                 }
  45.                
  46.         public void run() {
  47.                 short buffer[] = new short[minSize];
  48.                 int result = xmp.playFrame();
  49.                 while ((result == 0) || (loopForever==true)) {
  50.                        
  51.                         //note: result == -1 when stopModule() is called or when the module end is reached
  52.                         // however, this loop will continue playing if loopForever == true
  53.                         if (mStopModule == true)
  54.                         {
  55.                                 break;
  56.                         }
  57.                        
  58.                         if ((result != 0) && (loopForever==true))
  59.                         {
  60.                                 //restart mod from the beginnning
  61.                                 xmp.seek(0L);
  62.                                 result = xmp.playFrame();
  63.                         }
  64.  
  65.                        
  66.                         int size = xmp.softmixer();
  67.                         buffer = xmp.getBuffer(size, buffer);
  68.                         audio.write(buffer, 0, size / 2);
  69.                        
  70.                         while (paused) {
  71.                                 try {
  72.                                                 Thread.sleep(500);
  73.                                         } catch (InterruptedException e) {
  74.                                                 break;
  75.                                         }
  76.                         }
  77.                        
  78.                         //play next frame
  79.                         result = xmp.playFrame();
  80.                 }
  81.                
  82.                 audio.stop();
  83.                 xmp.endPlayer();
  84.                 xmp.releaseModule();
  85.         }
  86.  
  87.     }
  88.  
  89.  
  90.         protected void finalize() {
  91.         xmp.stopModule();
  92.         paused = false;
  93.         try {
  94.                         playThread.join();
  95.                 } catch (InterruptedException e) { }
  96.         xmp.deinit();
  97.     }
  98.    
  99.     public void play(String file, boolean bLoopMusic)
  100.     {
  101.         mStopModule=false;
  102.         if (xmp.loadModule(file) < 0) {
  103.                 return;
  104.         }
  105.         audio.play();
  106.         xmp.startPlayer();
  107.  
  108.         PlayRunnable playRunnable = new PlayRunnable(bLoopMusic);
  109.         playThread = new Thread(playRunnable);
  110.         playThread.start();
  111.     }
  112.    
  113.     public void stop() {
  114.         mStopModule=true;
  115.         xmp.stopModule();
  116.         paused = false;
  117.     }
  118.    
  119.     public void pause() {
  120.         paused = !paused;
  121.     }
  122.    
  123.     public int time() {
  124.         return xmp.time();
  125.     }
  126.  
  127.         public void seek(int seconds) {
  128.                 xmp.seek(seconds);
  129.         }
  130.        
  131.         public int getPlayTempo() {
  132.                 return xmp.getPlayTempo();
  133.         }
  134.        
  135.         public int getPlayBpm() {
  136.                 return xmp.getPlayBpm();
  137.         }
  138.        
  139.         public int getPlayPos() {
  140.                 return xmp.getPlayPos();
  141.         }
  142.        
  143.         public int getPlayPat() {
  144.                 return xmp.getPlayPat();
  145.         }
  146.        
  147.         public boolean isPaused() {
  148.                 return this.paused;
  149.         }
  150. }
  151.  
  152.  
  153.  
Parsed in 0.016 seconds, using GeSHi 1.0.8.4
alex
 
Posts: 275
Joined: Thu Jul 01, 2010 8:21 pm

Previous

Return to .MOD-Player

Who is online

Users browsing this forum: No registered users and 2 guests