< prev index next >

src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java

Print this page




  61 import javax.sound.sampled.AudioSystem;
  62 import javax.sound.sampled.LineUnavailableException;
  63 import javax.sound.sampled.SourceDataLine;
  64 
  65 /**
  66  * The software synthesizer class.
  67  *
  68  * @author Karl Helgason
  69  */
  70 public final class SoftSynthesizer implements AudioSynthesizer,
  71         ReferenceCountingDevice {
  72 
  73     protected static final class WeakAudioStream extends InputStream
  74     {
  75         private volatile AudioInputStream stream;
  76         public SoftAudioPusher pusher = null;
  77         public AudioInputStream jitter_stream = null;
  78         public SourceDataLine sourceDataLine = null;
  79         public volatile long silent_samples = 0;
  80         private int framesize = 0;
  81         private WeakReference<AudioInputStream> weak_stream_link;
  82         private AudioFloatConverter converter;
  83         private float[] silentbuffer = null;
  84         private int samplesize;
  85 
  86         public void setInputStream(AudioInputStream stream)
  87         {
  88             this.stream = stream;
  89         }
  90 

  91         public int available() throws IOException {
  92             AudioInputStream local_stream = stream;
  93             if(local_stream != null)
  94                 return local_stream.available();
  95             return 0;
  96         }
  97 

  98         public int read() throws IOException {
  99              byte[] b = new byte[1];
 100              if (read(b) == -1)
 101                   return -1;
 102              return b[0] & 0xFF;
 103         }
 104 

 105         public int read(byte[] b, int off, int len) throws IOException {
 106              AudioInputStream local_stream = stream;
 107              if(local_stream != null)
 108                  return local_stream.read(b, off, len);
 109              else
 110              {
 111                  int flen = len / samplesize;
 112                  if(silentbuffer == null || silentbuffer.length < flen)
 113                      silentbuffer = new float[flen];
 114                  converter.toByteArray(silentbuffer, flen, b, off);
 115 
 116                  silent_samples += (long)((len / framesize));
 117 
 118                  if(pusher != null)
 119                  if(weak_stream_link.get() == null)
 120                  {
 121                      Runnable runnable = new Runnable()
 122                      {
 123                          SoftAudioPusher _pusher = pusher;
 124                          AudioInputStream _jitter_stream = jitter_stream;
 125                          SourceDataLine _sourceDataLine = sourceDataLine;

 126                          public void run()
 127                          {
 128                              _pusher.stop();
 129                              if(_jitter_stream != null)
 130                                 try {
 131                                     _jitter_stream.close();
 132                                 } catch (IOException e) {
 133                                     e.printStackTrace();
 134                                 }
 135                              if(_sourceDataLine != null)
 136                                  _sourceDataLine.close();
 137                          }
 138                      };
 139                      pusher = null;
 140                      jitter_stream = null;
 141                      sourceDataLine = null;
 142                      new Thread(null, runnable, "Synthesizer",0,false).start();
 143                  }
 144                  return len;
 145              }
 146         }
 147 
 148         public WeakAudioStream(AudioInputStream stream) {
 149             this.stream = stream;
 150             weak_stream_link = new WeakReference<AudioInputStream>(stream);
 151             converter = AudioFloatConverter.getConverter(stream.getFormat());
 152             samplesize = stream.getFormat().getFrameSize() / stream.getFormat().getChannels();
 153             framesize = stream.getFormat().getFrameSize();
 154         }
 155 
 156         public AudioInputStream getAudioInputStream()
 157         {
 158             return new AudioInputStream(this, stream.getFormat(), AudioSystem.NOT_SPECIFIED);
 159         }
 160 

 161         public void close() throws IOException
 162         {
 163             AudioInputStream astream  = weak_stream_link.get();
 164             if(astream != null)
 165                 astream.close();
 166         }
 167     }
 168 
 169     private static class Info extends MidiDevice.Info {
 170         Info() {
 171             super(INFO_NAME, INFO_VENDOR, INFO_DESCRIPTION, INFO_VERSION);
 172         }
 173     }
 174 
 175     static final String INFO_NAME = "Gervill";
 176     static final String INFO_VENDOR = "OpenJDK";
 177     static final String INFO_DESCRIPTION = "Software MIDI Synthesizer";
 178     static final String INFO_VERSION = "1.0";
 179     static final MidiDevice.Info info = new Info();
 180 


 216 
 217     private SoftAudioPusher pusher = null;
 218     private AudioInputStream pusher_stream = null;
 219 
 220     private float controlrate = 147f;
 221 
 222     private boolean open = false;
 223     private boolean implicitOpen = false;
 224 
 225     private String resamplerType = "linear";
 226     private SoftResampler resampler = new SoftLinearResampler();
 227 
 228     private int number_of_midi_channels = 16;
 229     private int maxpoly = 64;
 230     private long latency = 200000; // 200 msec
 231     private boolean jitter_correction = false;
 232 
 233     private SoftMainMixer mainmixer;
 234     private SoftVoice[] voices;
 235 
 236     private Map<String, SoftTuning> tunings
 237             = new HashMap<String, SoftTuning>();
 238     private Map<String, SoftInstrument> inslist
 239             = new HashMap<String, SoftInstrument>();
 240     private Map<String, ModelInstrument> loadedlist
 241             = new HashMap<String, ModelInstrument>();
 242 
 243     private ArrayList<Receiver> recvslist = new ArrayList<Receiver>();
 244 
 245     private void getBuffers(ModelInstrument instrument,
 246             List<ModelByteBuffer> buffers) {
 247         for (ModelPerformer performer : instrument.getPerformers()) {
 248             if (performer.getOscillators() != null) {
 249                 for (ModelOscillator osc : performer.getOscillators()) {
 250                     if (osc instanceof ModelByteBufferWavetable) {
 251                         ModelByteBufferWavetable w = (ModelByteBufferWavetable)osc;
 252                         ModelByteBuffer buff = w.getBuffer();
 253                         if (buff != null)
 254                             buffers.add(buff);
 255                         buff = w.get8BitExtensionBuffer();
 256                         if (buff != null)
 257                             buffers.add(buff);
 258                     }
 259                 }
 260             }
 261         }
 262     }
 263 
 264     private boolean loadSamples(List<ModelInstrument> instruments) {
 265         if (largemode)
 266             return true;
 267         List<ModelByteBuffer> buffers = new ArrayList<ModelByteBuffer>();
 268         for (ModelInstrument instrument : instruments)
 269             getBuffers(instrument, buffers);
 270         try {
 271             ModelByteBuffer.loadAll(buffers);
 272         } catch (IOException e) {
 273             return false;
 274         }
 275         return true;
 276     }
 277 
 278     private boolean loadInstruments(List<ModelInstrument> instruments) {
 279         if (!isOpen())
 280             return false;
 281         if (!loadSamples(instruments))
 282             return false;
 283 
 284         synchronized (control_mutex) {
 285             if (channels != null)
 286                 for (SoftChannel c : channels)
 287                 {


 468     }
 469 
 470     float getControlRate() {
 471         return controlrate;
 472     }
 473 
 474     SoftVoice[] getVoices() {
 475         return voices;
 476     }
 477 
 478     SoftTuning getTuning(Patch patch) {
 479         String t_id = patchToString(patch);
 480         SoftTuning tuning = tunings.get(t_id);
 481         if (tuning == null) {
 482             tuning = new SoftTuning(patch);
 483             tunings.put(t_id, tuning);
 484         }
 485         return tuning;
 486     }
 487 

 488     public long getLatency() {
 489         synchronized (control_mutex) {
 490             return latency;
 491         }
 492     }
 493 

 494     public AudioFormat getFormat() {
 495         synchronized (control_mutex) {
 496             return format;
 497         }
 498     }
 499 

 500     public int getMaxPolyphony() {
 501         synchronized (control_mutex) {
 502             return maxpoly;
 503         }
 504     }
 505 

 506     public MidiChannel[] getChannels() {
 507 
 508         synchronized (control_mutex) {
 509             // if (external_channels == null) => the synthesizer is not open,
 510             // create 16 proxy channels
 511             // otherwise external_channels has the same length as channels array
 512             if (external_channels == null) {
 513                 external_channels = new SoftChannelProxy[16];
 514                 for (int i = 0; i < external_channels.length; i++)
 515                     external_channels[i] = new SoftChannelProxy();
 516             }
 517             MidiChannel[] ret;
 518             if (isOpen())
 519                 ret = new MidiChannel[channels.length];
 520             else
 521                 ret = new MidiChannel[16];
 522             for (int i = 0; i < ret.length; i++)
 523                 ret[i] = external_channels[i];
 524             return ret;
 525         }
 526     }
 527 

 528     public VoiceStatus[] getVoiceStatus() {
 529         if (!isOpen()) {
 530             VoiceStatus[] tempVoiceStatusArray
 531                     = new VoiceStatus[getMaxPolyphony()];
 532             for (int i = 0; i < tempVoiceStatusArray.length; i++) {
 533                 VoiceStatus b = new VoiceStatus();
 534                 b.active = false;
 535                 b.bank = 0;
 536                 b.channel = 0;
 537                 b.note = 0;
 538                 b.program = 0;
 539                 b.volume = 0;
 540                 tempVoiceStatusArray[i] = b;
 541             }
 542             return tempVoiceStatusArray;
 543         }
 544 
 545         synchronized (control_mutex) {
 546             VoiceStatus[] tempVoiceStatusArray = new VoiceStatus[voices.length];
 547             for (int i = 0; i < voices.length; i++) {
 548                 VoiceStatus a = voices[i];
 549                 VoiceStatus b = new VoiceStatus();
 550                 b.active = a.active;
 551                 b.bank = a.bank;
 552                 b.channel = a.channel;
 553                 b.note = a.note;
 554                 b.program = a.program;
 555                 b.volume = a.volume;
 556                 tempVoiceStatusArray[i] = b;
 557             }
 558             return tempVoiceStatusArray;
 559         }
 560     }
 561 

 562     public boolean isSoundbankSupported(Soundbank soundbank) {
 563         for (Instrument ins: soundbank.getInstruments())
 564             if (!(ins instanceof ModelInstrument))
 565                 return false;
 566         return true;
 567     }
 568 

 569     public boolean loadInstrument(Instrument instrument) {
 570         if (instrument == null || (!(instrument instanceof ModelInstrument))) {
 571             throw new IllegalArgumentException("Unsupported instrument: " +
 572                     instrument);
 573         }
 574         List<ModelInstrument> instruments = new ArrayList<ModelInstrument>();
 575         instruments.add((ModelInstrument)instrument);
 576         return loadInstruments(instruments);
 577     }
 578 

 579     public void unloadInstrument(Instrument instrument) {
 580         if (instrument == null || (!(instrument instanceof ModelInstrument))) {
 581             throw new IllegalArgumentException("Unsupported instrument: " +
 582                     instrument);
 583         }
 584         if (!isOpen())
 585             return;
 586 
 587         String pat = patchToString(instrument.getPatch());
 588         synchronized (control_mutex) {
 589             for (SoftChannel c: channels)
 590                 c.current_instrument = null;
 591             inslist.remove(pat);
 592             loadedlist.remove(pat);
 593             for (int i = 0; i < channels.length; i++) {
 594                 channels[i].allSoundOff();
 595             }
 596         }
 597     }
 598 

 599     public boolean remapInstrument(Instrument from, Instrument to) {
 600 
 601         if (from == null)
 602             throw new NullPointerException();
 603         if (to == null)
 604             throw new NullPointerException();
 605         if (!(from instanceof ModelInstrument)) {
 606             throw new IllegalArgumentException("Unsupported instrument: " +
 607                     from.toString());
 608         }
 609         if (!(to instanceof ModelInstrument)) {
 610             throw new IllegalArgumentException("Unsupported instrument: " +
 611                     to.toString());
 612         }
 613         if (!isOpen())
 614             return false;
 615 
 616         synchronized (control_mutex) {
 617             if (!loadedlist.containsValue(to))
 618                 throw new IllegalArgumentException("Instrument to is not loaded.");
 619             unloadInstrument(from);
 620             ModelMappedInstrument mfrom = new ModelMappedInstrument(
 621                     (ModelInstrument)to, from.getPatch());
 622             return loadInstrument(mfrom);
 623         }
 624     }
 625 

 626     public Soundbank getDefaultSoundbank() {
 627         synchronized (SoftSynthesizer.class) {
 628             if (defaultSoundBank != null)
 629                 return defaultSoundBank;
 630 
 631             List<PrivilegedAction<InputStream>> actions =
 632                 new ArrayList<PrivilegedAction<InputStream>>();
 633 
 634             actions.add(new PrivilegedAction<InputStream>() {

 635                 public InputStream run() {
 636                     File javahome = new File(System.getProperties()
 637                             .getProperty("java.home"));
 638                     File libaudio = new File(new File(javahome, "lib"), "audio");
 639                     if (libaudio.isDirectory()) {
 640                         File foundfile = null;
 641                         File[] files = libaudio.listFiles();
 642                         if (files != null) {
 643                             for (int i = 0; i < files.length; i++) {
 644                                 File file = files[i];
 645                                 if (file.isFile()) {
 646                                     String lname = file.getName().toLowerCase();
 647                                     if (lname.endsWith(".sf2")
 648                                             || lname.endsWith(".dls")) {
 649                                         if (foundfile == null
 650                                                 || (file.length() > foundfile
 651                                                         .length())) {
 652                                             foundfile = file;
 653                                         }
 654                                     }
 655                                 }
 656                             }
 657                         }
 658                         if (foundfile != null) {
 659                             try {
 660                                 return new FileInputStream(foundfile);
 661                             } catch (IOException e) {
 662                             }
 663                         }
 664                     }
 665                     return null;
 666                 }
 667             });
 668 
 669             actions.add(new PrivilegedAction<InputStream>() {

 670                 public InputStream run() {
 671                     if (System.getProperties().getProperty("os.name")
 672                             .startsWith("Linux")) {
 673 
 674                         File[] systemSoundFontsDir = new File[] {
 675                             /* Arch, Fedora, Mageia */
 676                             new File("/usr/share/soundfonts/"),
 677                             new File("/usr/local/share/soundfonts/"),
 678                             /* Debian, Gentoo, OpenSUSE, Ubuntu */
 679                             new File("/usr/share/sounds/sf2/"),
 680                             new File("/usr/local/share/sounds/sf2/"),
 681                         };
 682 
 683                         /*
 684                          * Look for a default.sf2
 685                          */
 686                         for (File systemSoundFontDir : systemSoundFontsDir) {
 687                             if (systemSoundFontDir.isDirectory()) {
 688                                 File defaultSoundFont = new File(systemSoundFontDir, "default.sf2");
 689                                 if (defaultSoundFont.isFile()) {
 690                                     try {
 691                                         return new FileInputStream(defaultSoundFont);
 692                                     } catch (IOException e) {
 693                                         // continue with lookup
 694                                     }
 695                                 }
 696                             }
 697                         }
 698                     }
 699                     return null;
 700                 }
 701             });
 702 
 703             actions.add(new PrivilegedAction<InputStream>() {

 704                 public InputStream run() {
 705                     if (System.getProperties().getProperty("os.name")
 706                             .startsWith("Windows")) {
 707                         File gm_dls = new File(System.getenv("SystemRoot")
 708                                 + "\\system32\\drivers\\gm.dls");
 709                         if (gm_dls.isFile()) {
 710                             try {
 711                                 return new FileInputStream(gm_dls);
 712                             } catch (IOException e) {
 713                             }
 714                         }
 715                     }
 716                     return null;
 717                 }
 718             });
 719 
 720             actions.add(new PrivilegedAction<InputStream>() {

 721                 public InputStream run() {
 722                     /*
 723                      * Try to load saved generated soundbank
 724                      */
 725                     File userhome = new File(System.getProperty("user.home"),
 726                             ".gervill");
 727                     File emg_soundbank_file = new File(userhome,
 728                             "soundbank-emg.sf2");
 729                     if (emg_soundbank_file.isFile()) {
 730                         try {
 731                             return new FileInputStream(emg_soundbank_file);
 732                         } catch (IOException e) {
 733                         }
 734                     }
 735                     return null;
 736                 }
 737             });
 738 
 739             for (PrivilegedAction<InputStream> action : actions) {
 740                 try {


 781                                 if (emg_soundbank_file.isFile()) {
 782                                     return null;
 783                                 }
 784                                 return new FileOutputStream(emg_soundbank_file);
 785                             } catch (final FileNotFoundException ignored) {
 786                             }
 787                             return null;
 788                         });
 789                 if (out != null) {
 790                     try {
 791                         ((SF2Soundbank) defaultSoundBank).save(out);
 792                         out.close();
 793                     } catch (final IOException ignored) {
 794                     }
 795                 }
 796             }
 797         }
 798         return defaultSoundBank;
 799     }
 800 

 801     public Instrument[] getAvailableInstruments() {
 802         Soundbank defsbk = getDefaultSoundbank();
 803         if (defsbk == null)
 804             return new Instrument[0];
 805         Instrument[] inslist_array = defsbk.getInstruments();
 806         Arrays.sort(inslist_array, new ModelInstrumentComparator());
 807         return inslist_array;
 808     }
 809 

 810     public Instrument[] getLoadedInstruments() {
 811         if (!isOpen())
 812             return new Instrument[0];
 813 
 814         synchronized (control_mutex) {
 815             ModelInstrument[] inslist_array =
 816                     new ModelInstrument[loadedlist.values().size()];
 817             loadedlist.values().toArray(inslist_array);
 818             Arrays.sort(inslist_array, new ModelInstrumentComparator());
 819             return inslist_array;
 820         }
 821     }
 822 

 823     public boolean loadAllInstruments(Soundbank soundbank) {
 824         List<ModelInstrument> instruments = new ArrayList<ModelInstrument>();
 825         for (Instrument ins: soundbank.getInstruments()) {
 826             if (ins == null || !(ins instanceof ModelInstrument)) {
 827                 throw new IllegalArgumentException(
 828                         "Unsupported instrument: " + ins);
 829             }
 830             instruments.add((ModelInstrument)ins);
 831         }
 832         return loadInstruments(instruments);
 833     }
 834 

 835     public void unloadAllInstruments(Soundbank soundbank) {
 836         if (soundbank == null || !isSoundbankSupported(soundbank))
 837             throw new IllegalArgumentException("Unsupported soundbank: " + soundbank);
 838 
 839         if (!isOpen())
 840             return;
 841 
 842         for (Instrument ins: soundbank.getInstruments()) {
 843             if (ins instanceof ModelInstrument) {
 844                 unloadInstrument(ins);
 845             }
 846         }
 847     }
 848 

 849     public boolean loadInstruments(Soundbank soundbank, Patch[] patchList) {
 850         List<ModelInstrument> instruments = new ArrayList<ModelInstrument>();
 851         for (Patch patch: patchList) {
 852             Instrument ins = soundbank.getInstrument(patch);
 853             if (ins == null || !(ins instanceof ModelInstrument)) {
 854                 throw new IllegalArgumentException(
 855                         "Unsupported instrument: " + ins);
 856             }
 857             instruments.add((ModelInstrument)ins);
 858         }
 859         return loadInstruments(instruments);
 860     }
 861 

 862     public void unloadInstruments(Soundbank soundbank, Patch[] patchList) {
 863         if (soundbank == null || !isSoundbankSupported(soundbank))
 864             throw new IllegalArgumentException("Unsupported soundbank: " + soundbank);
 865 
 866         if (!isOpen())
 867             return;
 868 
 869         for (Patch pat: patchList) {
 870             Instrument ins = soundbank.getInstrument(pat);
 871             if (ins instanceof ModelInstrument) {
 872                 unloadInstrument(ins);
 873             }
 874         }
 875     }
 876 

 877     public MidiDevice.Info getDeviceInfo() {
 878         return info;
 879     }
 880 
 881     private Properties getStoredProperties() {
 882         return AccessController
 883                 .doPrivileged((PrivilegedAction<Properties>) () -> {
 884                     Properties p = new Properties();
 885                     String notePath = "/com/sun/media/sound/softsynthesizer";
 886                     try {
 887                         Preferences prefroot = Preferences.userRoot();
 888                         if (prefroot.nodeExists(notePath)) {
 889                             Preferences prefs = prefroot.node(notePath);
 890                             String[] prefs_keys = prefs.keys();
 891                             for (String prefs_key : prefs_keys) {
 892                                 String val = prefs.get(prefs_key, null);
 893                                 if (val != null) {
 894                                     p.setProperty(prefs_key, val);
 895                                 }
 896                             }
 897                         }
 898                     } catch (final BackingStoreException ignored) {
 899                     }
 900                     return p;
 901                 });
 902     }
 903 

 904     public AudioSynthesizerPropertyInfo[] getPropertyInfo(Map<String, Object> info) {
 905         List<AudioSynthesizerPropertyInfo> list =
 906                 new ArrayList<AudioSynthesizerPropertyInfo>();
 907 
 908         AudioSynthesizerPropertyInfo item;
 909 
 910         // If info != null or synthesizer is closed
 911         //   we return how the synthesizer will be set on next open
 912         // If info == null and synthesizer is open
 913         //   we return current synthesizer properties.
 914         boolean o = info == null && open;
 915 
 916         item = new AudioSynthesizerPropertyInfo("interpolation", o?resamplerType:"linear");
 917         item.choices = new String[]{"linear", "linear1", "linear2", "cubic",
 918                                     "lanczos", "sinc", "point"};
 919         item.description = "Interpolation method";
 920         list.add(item);
 921 
 922         item = new AudioSynthesizerPropertyInfo("control rate", o?controlrate:147f);
 923         item.description = "Control rate";
 924         list.add(item);
 925 
 926         item = new AudioSynthesizerPropertyInfo("format",


1041                     Number n = (Number) v;
1042                     if (c == Byte.class)
1043                         item2.value = Byte.valueOf(n.byteValue());
1044                     if (c == Short.class)
1045                         item2.value = Short.valueOf(n.shortValue());
1046                     if (c == Integer.class)
1047                         item2.value = Integer.valueOf(n.intValue());
1048                     if (c == Long.class)
1049                         item2.value = Long.valueOf(n.longValue());
1050                     if (c == Float.class)
1051                         item2.value = Float.valueOf(n.floatValue());
1052                     if (c == Double.class)
1053                         item2.value = Double.valueOf(n.doubleValue());
1054                 }
1055             }
1056         }
1057 
1058         return items;
1059     }
1060 

1061     public void open() throws MidiUnavailableException {
1062         if (isOpen()) {
1063             synchronized (control_mutex) {
1064                 implicitOpen = false;
1065             }
1066             return;
1067         }
1068         open(null, null);
1069     }
1070 

1071     public void open(SourceDataLine line, Map<String, Object> info) throws MidiUnavailableException {
1072         if (isOpen()) {
1073             synchronized (control_mutex) {
1074                 implicitOpen = false;
1075             }
1076             return;
1077         }
1078         synchronized (control_mutex) {
1079             try {
1080                 if (line != null) {
1081                     // can throw IllegalArgumentException
1082                     setFormat(line.getFormat());
1083                 }
1084 
1085                 AudioInputStream ais = openStream(getFormat(), info);
1086 
1087                 weakstream = new WeakAudioStream(ais);
1088                 ais = weakstream.getAudioInputStream();
1089 
1090                 if (line == null)


1145                 if(weakstream != null)
1146                 {
1147                     weakstream.pusher = pusher;
1148                     weakstream.sourceDataLine = sourceDataLine;
1149                 }
1150 
1151             } catch (final LineUnavailableException | SecurityException
1152                     | IllegalArgumentException e) {
1153                 if (isOpen()) {
1154                     close();
1155                 }
1156                 // am: need MidiUnavailableException(Throwable) ctor!
1157                 MidiUnavailableException ex = new MidiUnavailableException(
1158                         "Can not open line");
1159                 ex.initCause(e);
1160                 throw ex;
1161             }
1162         }
1163     }
1164 

1165     public AudioInputStream openStream(AudioFormat targetFormat,
1166             Map<String, Object> info) throws MidiUnavailableException {
1167 
1168         if (isOpen())
1169             throw new MidiUnavailableException("Synthesizer is already open");
1170 
1171         synchronized (control_mutex) {
1172 
1173             gmmode = 0;
1174             voice_allocation_mode = 0;
1175 
1176             processPropertyInfo(info);
1177 
1178             open = true;
1179             implicitOpen = false;
1180 
1181             if (targetFormat != null)
1182                 setFormat(targetFormat);
1183 
1184             if (load_default_soundbank)


1226                 }
1227             }
1228 
1229             for (int i = 0; i < channels.length; i++)
1230                 external_channels[i].setChannel(channels[i]);
1231 
1232             for (SoftVoice voice: getVoices())
1233                 voice.resampler = resampler.openStreamer();
1234 
1235             for (Receiver recv: getReceivers()) {
1236                 SoftReceiver srecv = ((SoftReceiver)recv);
1237                 srecv.open = open;
1238                 srecv.mainmixer = mainmixer;
1239                 srecv.midimessages = mainmixer.midimessages;
1240             }
1241 
1242             return mainmixer.getInputStream();
1243         }
1244     }
1245 

1246     public void close() {
1247 
1248         if (!isOpen())
1249             return;
1250 
1251         SoftAudioPusher pusher_to_be_closed = null;
1252         AudioInputStream pusher_stream_to_be_closed = null;
1253         synchronized (control_mutex) {
1254             if (pusher != null) {
1255                 pusher_to_be_closed = pusher;
1256                 pusher_stream_to_be_closed = pusher_stream;
1257                 pusher = null;
1258                 pusher_stream = null;
1259             }
1260         }
1261 
1262         if (pusher_to_be_closed != null) {
1263             // Pusher must not be closed synchronized against control_mutex,
1264             // this may result in synchronized conflict between pusher
1265             // and current thread.


1284 
1285             if (external_channels != null)
1286                 for (int i = 0; i < external_channels.length; i++)
1287                     external_channels[i].setChannel(null);
1288 
1289             if (sourceDataLine != null) {
1290                 sourceDataLine.close();
1291                 sourceDataLine = null;
1292             }
1293 
1294             inslist.clear();
1295             loadedlist.clear();
1296             tunings.clear();
1297 
1298             while (recvslist.size() != 0)
1299                 recvslist.get(recvslist.size() - 1).close();
1300 
1301         }
1302     }
1303 

1304     public boolean isOpen() {
1305         synchronized (control_mutex) {
1306             return open;
1307         }
1308     }
1309 

1310     public long getMicrosecondPosition() {
1311 
1312         if (!isOpen())
1313             return 0;
1314 
1315         synchronized (control_mutex) {
1316             return mainmixer.getMicrosecondPosition();
1317         }
1318     }
1319 

1320     public int getMaxReceivers() {
1321         return -1;
1322     }
1323 

1324     public int getMaxTransmitters() {
1325         return 0;
1326     }
1327 

1328     public Receiver getReceiver() throws MidiUnavailableException {
1329 
1330         synchronized (control_mutex) {
1331             SoftReceiver receiver = new SoftReceiver(this);
1332             receiver.open = open;
1333             recvslist.add(receiver);
1334             return receiver;
1335         }
1336     }
1337 

1338     public List<Receiver> getReceivers() {
1339 
1340         synchronized (control_mutex) {
1341             ArrayList<Receiver> recvs = new ArrayList<Receiver>();
1342             recvs.addAll(recvslist);
1343             return recvs;
1344         }
1345     }
1346 

1347     public Transmitter getTransmitter() throws MidiUnavailableException {
1348 
1349         throw new MidiUnavailableException("No transmitter available");
1350     }
1351 

1352     public List<Transmitter> getTransmitters() {
1353 
1354         return new ArrayList<Transmitter>();
1355     }
1356 

1357     public Receiver getReceiverReferenceCounting()
1358             throws MidiUnavailableException {
1359 
1360         if (!isOpen()) {
1361             open();
1362             synchronized (control_mutex) {
1363                 implicitOpen = true;
1364             }
1365         }
1366 
1367         return getReceiver();
1368     }
1369 

1370     public Transmitter getTransmitterReferenceCounting()
1371             throws MidiUnavailableException {
1372 
1373         throw new MidiUnavailableException("No transmitter available");
1374     }
1375 }


  61 import javax.sound.sampled.AudioSystem;
  62 import javax.sound.sampled.LineUnavailableException;
  63 import javax.sound.sampled.SourceDataLine;
  64 
  65 /**
  66  * The software synthesizer class.
  67  *
  68  * @author Karl Helgason
  69  */
  70 public final class SoftSynthesizer implements AudioSynthesizer,
  71         ReferenceCountingDevice {
  72 
  73     protected static final class WeakAudioStream extends InputStream
  74     {
  75         private volatile AudioInputStream stream;
  76         public SoftAudioPusher pusher = null;
  77         public AudioInputStream jitter_stream = null;
  78         public SourceDataLine sourceDataLine = null;
  79         public volatile long silent_samples = 0;
  80         private int framesize = 0;
  81         private final WeakReference<AudioInputStream> weak_stream_link;
  82         private final AudioFloatConverter converter;
  83         private float[] silentbuffer = null;
  84         private final int samplesize;
  85 
  86         public void setInputStream(AudioInputStream stream)
  87         {
  88             this.stream = stream;
  89         }
  90 
  91         @Override
  92         public int available() throws IOException {
  93             AudioInputStream local_stream = stream;
  94             if(local_stream != null)
  95                 return local_stream.available();
  96             return 0;
  97         }
  98 
  99         @Override
 100         public int read() throws IOException {
 101              byte[] b = new byte[1];
 102              if (read(b) == -1)
 103                   return -1;
 104              return b[0] & 0xFF;
 105         }
 106 
 107         @Override
 108         public int read(byte[] b, int off, int len) throws IOException {
 109              AudioInputStream local_stream = stream;
 110              if(local_stream != null)
 111                  return local_stream.read(b, off, len);
 112              else
 113              {
 114                  int flen = len / samplesize;
 115                  if(silentbuffer == null || silentbuffer.length < flen)
 116                      silentbuffer = new float[flen];
 117                  converter.toByteArray(silentbuffer, flen, b, off);
 118 
 119                  silent_samples += (long)((len / framesize));
 120 
 121                  if(pusher != null)
 122                  if(weak_stream_link.get() == null)
 123                  {
 124                      Runnable runnable = new Runnable()
 125                      {
 126                          SoftAudioPusher _pusher = pusher;
 127                          AudioInputStream _jitter_stream = jitter_stream;
 128                          SourceDataLine _sourceDataLine = sourceDataLine;
 129                          @Override
 130                          public void run()
 131                          {
 132                              _pusher.stop();
 133                              if(_jitter_stream != null)
 134                                 try {
 135                                     _jitter_stream.close();
 136                                 } catch (IOException e) {
 137                                     e.printStackTrace();
 138                                 }
 139                              if(_sourceDataLine != null)
 140                                  _sourceDataLine.close();
 141                          }
 142                      };
 143                      pusher = null;
 144                      jitter_stream = null;
 145                      sourceDataLine = null;
 146                      new Thread(null, runnable, "Synthesizer",0,false).start();
 147                  }
 148                  return len;
 149              }
 150         }
 151 
 152         public WeakAudioStream(AudioInputStream stream) {
 153             this.stream = stream;
 154             weak_stream_link = new WeakReference<>(stream);
 155             converter = AudioFloatConverter.getConverter(stream.getFormat());
 156             samplesize = stream.getFormat().getFrameSize() / stream.getFormat().getChannels();
 157             framesize = stream.getFormat().getFrameSize();
 158         }
 159 
 160         public AudioInputStream getAudioInputStream()
 161         {
 162             return new AudioInputStream(this, stream.getFormat(), AudioSystem.NOT_SPECIFIED);
 163         }
 164 
 165         @Override
 166         public void close() throws IOException
 167         {
 168             AudioInputStream astream  = weak_stream_link.get();
 169             if(astream != null)
 170                 astream.close();
 171         }
 172     }
 173 
 174     private static class Info extends MidiDevice.Info {
 175         Info() {
 176             super(INFO_NAME, INFO_VENDOR, INFO_DESCRIPTION, INFO_VERSION);
 177         }
 178     }
 179 
 180     static final String INFO_NAME = "Gervill";
 181     static final String INFO_VENDOR = "OpenJDK";
 182     static final String INFO_DESCRIPTION = "Software MIDI Synthesizer";
 183     static final String INFO_VERSION = "1.0";
 184     static final MidiDevice.Info info = new Info();
 185 


 221 
 222     private SoftAudioPusher pusher = null;
 223     private AudioInputStream pusher_stream = null;
 224 
 225     private float controlrate = 147f;
 226 
 227     private boolean open = false;
 228     private boolean implicitOpen = false;
 229 
 230     private String resamplerType = "linear";
 231     private SoftResampler resampler = new SoftLinearResampler();
 232 
 233     private int number_of_midi_channels = 16;
 234     private int maxpoly = 64;
 235     private long latency = 200000; // 200 msec
 236     private boolean jitter_correction = false;
 237 
 238     private SoftMainMixer mainmixer;
 239     private SoftVoice[] voices;
 240 
 241     private final Map<String, SoftTuning> tunings = new HashMap<>();
 242     private final Map<String, SoftInstrument> inslist = new HashMap<>();
 243     private final Map<String, ModelInstrument> loadedlist = new HashMap<>();
 244     private final ArrayList<Receiver> recvslist = new ArrayList<>();




 245 
 246     private void getBuffers(ModelInstrument instrument,
 247             List<ModelByteBuffer> buffers) {
 248         for (ModelPerformer performer : instrument.getPerformers()) {
 249             if (performer.getOscillators() != null) {
 250                 for (ModelOscillator osc : performer.getOscillators()) {
 251                     if (osc instanceof ModelByteBufferWavetable) {
 252                         ModelByteBufferWavetable w = (ModelByteBufferWavetable)osc;
 253                         ModelByteBuffer buff = w.getBuffer();
 254                         if (buff != null)
 255                             buffers.add(buff);
 256                         buff = w.get8BitExtensionBuffer();
 257                         if (buff != null)
 258                             buffers.add(buff);
 259                     }
 260                 }
 261             }
 262         }
 263     }
 264 
 265     private boolean loadSamples(List<ModelInstrument> instruments) {
 266         if (largemode)
 267             return true;
 268         List<ModelByteBuffer> buffers = new ArrayList<>();
 269         for (ModelInstrument instrument : instruments)
 270             getBuffers(instrument, buffers);
 271         try {
 272             ModelByteBuffer.loadAll(buffers);
 273         } catch (IOException e) {
 274             return false;
 275         }
 276         return true;
 277     }
 278 
 279     private boolean loadInstruments(List<ModelInstrument> instruments) {
 280         if (!isOpen())
 281             return false;
 282         if (!loadSamples(instruments))
 283             return false;
 284 
 285         synchronized (control_mutex) {
 286             if (channels != null)
 287                 for (SoftChannel c : channels)
 288                 {


 469     }
 470 
 471     float getControlRate() {
 472         return controlrate;
 473     }
 474 
 475     SoftVoice[] getVoices() {
 476         return voices;
 477     }
 478 
 479     SoftTuning getTuning(Patch patch) {
 480         String t_id = patchToString(patch);
 481         SoftTuning tuning = tunings.get(t_id);
 482         if (tuning == null) {
 483             tuning = new SoftTuning(patch);
 484             tunings.put(t_id, tuning);
 485         }
 486         return tuning;
 487     }
 488 
 489     @Override
 490     public long getLatency() {
 491         synchronized (control_mutex) {
 492             return latency;
 493         }
 494     }
 495 
 496     @Override
 497     public AudioFormat getFormat() {
 498         synchronized (control_mutex) {
 499             return format;
 500         }
 501     }
 502 
 503     @Override
 504     public int getMaxPolyphony() {
 505         synchronized (control_mutex) {
 506             return maxpoly;
 507         }
 508     }
 509 
 510     @Override
 511     public MidiChannel[] getChannels() {
 512 
 513         synchronized (control_mutex) {
 514             // if (external_channels == null) => the synthesizer is not open,
 515             // create 16 proxy channels
 516             // otherwise external_channels has the same length as channels array
 517             if (external_channels == null) {
 518                 external_channels = new SoftChannelProxy[16];
 519                 for (int i = 0; i < external_channels.length; i++)
 520                     external_channels[i] = new SoftChannelProxy();
 521             }
 522             MidiChannel[] ret;
 523             if (isOpen())
 524                 ret = new MidiChannel[channels.length];
 525             else
 526                 ret = new MidiChannel[16];
 527             for (int i = 0; i < ret.length; i++)
 528                 ret[i] = external_channels[i];
 529             return ret;
 530         }
 531     }
 532 
 533     @Override
 534     public VoiceStatus[] getVoiceStatus() {
 535         if (!isOpen()) {
 536             VoiceStatus[] tempVoiceStatusArray
 537                     = new VoiceStatus[getMaxPolyphony()];
 538             for (int i = 0; i < tempVoiceStatusArray.length; i++) {
 539                 VoiceStatus b = new VoiceStatus();
 540                 b.active = false;
 541                 b.bank = 0;
 542                 b.channel = 0;
 543                 b.note = 0;
 544                 b.program = 0;
 545                 b.volume = 0;
 546                 tempVoiceStatusArray[i] = b;
 547             }
 548             return tempVoiceStatusArray;
 549         }
 550 
 551         synchronized (control_mutex) {
 552             VoiceStatus[] tempVoiceStatusArray = new VoiceStatus[voices.length];
 553             for (int i = 0; i < voices.length; i++) {
 554                 VoiceStatus a = voices[i];
 555                 VoiceStatus b = new VoiceStatus();
 556                 b.active = a.active;
 557                 b.bank = a.bank;
 558                 b.channel = a.channel;
 559                 b.note = a.note;
 560                 b.program = a.program;
 561                 b.volume = a.volume;
 562                 tempVoiceStatusArray[i] = b;
 563             }
 564             return tempVoiceStatusArray;
 565         }
 566     }
 567 
 568     @Override
 569     public boolean isSoundbankSupported(Soundbank soundbank) {
 570         for (Instrument ins: soundbank.getInstruments())
 571             if (!(ins instanceof ModelInstrument))
 572                 return false;
 573         return true;
 574     }
 575 
 576     @Override
 577     public boolean loadInstrument(Instrument instrument) {
 578         if (instrument == null || (!(instrument instanceof ModelInstrument))) {
 579             throw new IllegalArgumentException("Unsupported instrument: " +
 580                     instrument);
 581         }
 582         List<ModelInstrument> instruments = new ArrayList<>();
 583         instruments.add((ModelInstrument)instrument);
 584         return loadInstruments(instruments);
 585     }
 586 
 587     @Override
 588     public void unloadInstrument(Instrument instrument) {
 589         if (instrument == null || (!(instrument instanceof ModelInstrument))) {
 590             throw new IllegalArgumentException("Unsupported instrument: " +
 591                     instrument);
 592         }
 593         if (!isOpen())
 594             return;
 595 
 596         String pat = patchToString(instrument.getPatch());
 597         synchronized (control_mutex) {
 598             for (SoftChannel c: channels)
 599                 c.current_instrument = null;
 600             inslist.remove(pat);
 601             loadedlist.remove(pat);
 602             for (int i = 0; i < channels.length; i++) {
 603                 channels[i].allSoundOff();
 604             }
 605         }
 606     }
 607 
 608     @Override
 609     public boolean remapInstrument(Instrument from, Instrument to) {
 610 
 611         if (from == null)
 612             throw new NullPointerException();
 613         if (to == null)
 614             throw new NullPointerException();
 615         if (!(from instanceof ModelInstrument)) {
 616             throw new IllegalArgumentException("Unsupported instrument: " +
 617                     from.toString());
 618         }
 619         if (!(to instanceof ModelInstrument)) {
 620             throw new IllegalArgumentException("Unsupported instrument: " +
 621                     to.toString());
 622         }
 623         if (!isOpen())
 624             return false;
 625 
 626         synchronized (control_mutex) {
 627             if (!loadedlist.containsValue(to))
 628                 throw new IllegalArgumentException("Instrument to is not loaded.");
 629             unloadInstrument(from);
 630             ModelMappedInstrument mfrom = new ModelMappedInstrument(
 631                     (ModelInstrument)to, from.getPatch());
 632             return loadInstrument(mfrom);
 633         }
 634     }
 635 
 636     @Override
 637     public Soundbank getDefaultSoundbank() {
 638         synchronized (SoftSynthesizer.class) {
 639             if (defaultSoundBank != null)
 640                 return defaultSoundBank;
 641 
 642             List<PrivilegedAction<InputStream>> actions = new ArrayList<>();

 643 
 644             actions.add(new PrivilegedAction<InputStream>() {
 645                 @Override
 646                 public InputStream run() {
 647                     File javahome = new File(System.getProperties()
 648                             .getProperty("java.home"));
 649                     File libaudio = new File(new File(javahome, "lib"), "audio");
 650                     if (libaudio.isDirectory()) {
 651                         File foundfile = null;
 652                         File[] files = libaudio.listFiles();
 653                         if (files != null) {
 654                             for (int i = 0; i < files.length; i++) {
 655                                 File file = files[i];
 656                                 if (file.isFile()) {
 657                                     String lname = file.getName().toLowerCase();
 658                                     if (lname.endsWith(".sf2")
 659                                             || lname.endsWith(".dls")) {
 660                                         if (foundfile == null
 661                                                 || (file.length() > foundfile
 662                                                         .length())) {
 663                                             foundfile = file;
 664                                         }
 665                                     }
 666                                 }
 667                             }
 668                         }
 669                         if (foundfile != null) {
 670                             try {
 671                                 return new FileInputStream(foundfile);
 672                             } catch (IOException e) {
 673                             }
 674                         }
 675                     }
 676                     return null;
 677                 }
 678             });
 679 
 680             actions.add(new PrivilegedAction<InputStream>() {
 681                 @Override
 682                 public InputStream run() {
 683                     if (System.getProperties().getProperty("os.name")
 684                             .startsWith("Linux")) {
 685 
 686                         File[] systemSoundFontsDir = new File[] {
 687                             /* Arch, Fedora, Mageia */
 688                             new File("/usr/share/soundfonts/"),
 689                             new File("/usr/local/share/soundfonts/"),
 690                             /* Debian, Gentoo, OpenSUSE, Ubuntu */
 691                             new File("/usr/share/sounds/sf2/"),
 692                             new File("/usr/local/share/sounds/sf2/"),
 693                         };
 694 
 695                         /*
 696                          * Look for a default.sf2
 697                          */
 698                         for (File systemSoundFontDir : systemSoundFontsDir) {
 699                             if (systemSoundFontDir.isDirectory()) {
 700                                 File defaultSoundFont = new File(systemSoundFontDir, "default.sf2");
 701                                 if (defaultSoundFont.isFile()) {
 702                                     try {
 703                                         return new FileInputStream(defaultSoundFont);
 704                                     } catch (IOException e) {
 705                                         // continue with lookup
 706                                     }
 707                                 }
 708                             }
 709                         }
 710                     }
 711                     return null;
 712                 }
 713             });
 714 
 715             actions.add(new PrivilegedAction<InputStream>() {
 716                 @Override
 717                 public InputStream run() {
 718                     if (System.getProperties().getProperty("os.name")
 719                             .startsWith("Windows")) {
 720                         File gm_dls = new File(System.getenv("SystemRoot")
 721                                 + "\\system32\\drivers\\gm.dls");
 722                         if (gm_dls.isFile()) {
 723                             try {
 724                                 return new FileInputStream(gm_dls);
 725                             } catch (IOException e) {
 726                             }
 727                         }
 728                     }
 729                     return null;
 730                 }
 731             });
 732 
 733             actions.add(new PrivilegedAction<InputStream>() {
 734                 @Override
 735                 public InputStream run() {
 736                     /*
 737                      * Try to load saved generated soundbank
 738                      */
 739                     File userhome = new File(System.getProperty("user.home"),
 740                             ".gervill");
 741                     File emg_soundbank_file = new File(userhome,
 742                             "soundbank-emg.sf2");
 743                     if (emg_soundbank_file.isFile()) {
 744                         try {
 745                             return new FileInputStream(emg_soundbank_file);
 746                         } catch (IOException e) {
 747                         }
 748                     }
 749                     return null;
 750                 }
 751             });
 752 
 753             for (PrivilegedAction<InputStream> action : actions) {
 754                 try {


 795                                 if (emg_soundbank_file.isFile()) {
 796                                     return null;
 797                                 }
 798                                 return new FileOutputStream(emg_soundbank_file);
 799                             } catch (final FileNotFoundException ignored) {
 800                             }
 801                             return null;
 802                         });
 803                 if (out != null) {
 804                     try {
 805                         ((SF2Soundbank) defaultSoundBank).save(out);
 806                         out.close();
 807                     } catch (final IOException ignored) {
 808                     }
 809                 }
 810             }
 811         }
 812         return defaultSoundBank;
 813     }
 814 
 815     @Override
 816     public Instrument[] getAvailableInstruments() {
 817         Soundbank defsbk = getDefaultSoundbank();
 818         if (defsbk == null)
 819             return new Instrument[0];
 820         Instrument[] inslist_array = defsbk.getInstruments();
 821         Arrays.sort(inslist_array, new ModelInstrumentComparator());
 822         return inslist_array;
 823     }
 824 
 825     @Override
 826     public Instrument[] getLoadedInstruments() {
 827         if (!isOpen())
 828             return new Instrument[0];
 829 
 830         synchronized (control_mutex) {
 831             ModelInstrument[] inslist_array =
 832                     new ModelInstrument[loadedlist.values().size()];
 833             loadedlist.values().toArray(inslist_array);
 834             Arrays.sort(inslist_array, new ModelInstrumentComparator());
 835             return inslist_array;
 836         }
 837     }
 838 
 839     @Override
 840     public boolean loadAllInstruments(Soundbank soundbank) {
 841         List<ModelInstrument> instruments = new ArrayList<>();
 842         for (Instrument ins: soundbank.getInstruments()) {
 843             if (ins == null || !(ins instanceof ModelInstrument)) {
 844                 throw new IllegalArgumentException(
 845                         "Unsupported instrument: " + ins);
 846             }
 847             instruments.add((ModelInstrument)ins);
 848         }
 849         return loadInstruments(instruments);
 850     }
 851 
 852     @Override
 853     public void unloadAllInstruments(Soundbank soundbank) {
 854         if (soundbank == null || !isSoundbankSupported(soundbank))
 855             throw new IllegalArgumentException("Unsupported soundbank: " + soundbank);
 856 
 857         if (!isOpen())
 858             return;
 859 
 860         for (Instrument ins: soundbank.getInstruments()) {
 861             if (ins instanceof ModelInstrument) {
 862                 unloadInstrument(ins);
 863             }
 864         }
 865     }
 866 
 867     @Override
 868     public boolean loadInstruments(Soundbank soundbank, Patch[] patchList) {
 869         List<ModelInstrument> instruments = new ArrayList<>();
 870         for (Patch patch: patchList) {
 871             Instrument ins = soundbank.getInstrument(patch);
 872             if (ins == null || !(ins instanceof ModelInstrument)) {
 873                 throw new IllegalArgumentException(
 874                         "Unsupported instrument: " + ins);
 875             }
 876             instruments.add((ModelInstrument)ins);
 877         }
 878         return loadInstruments(instruments);
 879     }
 880 
 881     @Override
 882     public void unloadInstruments(Soundbank soundbank, Patch[] patchList) {
 883         if (soundbank == null || !isSoundbankSupported(soundbank))
 884             throw new IllegalArgumentException("Unsupported soundbank: " + soundbank);
 885 
 886         if (!isOpen())
 887             return;
 888 
 889         for (Patch pat: patchList) {
 890             Instrument ins = soundbank.getInstrument(pat);
 891             if (ins instanceof ModelInstrument) {
 892                 unloadInstrument(ins);
 893             }
 894         }
 895     }
 896 
 897     @Override
 898     public MidiDevice.Info getDeviceInfo() {
 899         return info;
 900     }
 901 
 902     private Properties getStoredProperties() {
 903         return AccessController
 904                 .doPrivileged((PrivilegedAction<Properties>) () -> {
 905                     Properties p = new Properties();
 906                     String notePath = "/com/sun/media/sound/softsynthesizer";
 907                     try {
 908                         Preferences prefroot = Preferences.userRoot();
 909                         if (prefroot.nodeExists(notePath)) {
 910                             Preferences prefs = prefroot.node(notePath);
 911                             String[] prefs_keys = prefs.keys();
 912                             for (String prefs_key : prefs_keys) {
 913                                 String val = prefs.get(prefs_key, null);
 914                                 if (val != null) {
 915                                     p.setProperty(prefs_key, val);
 916                                 }
 917                             }
 918                         }
 919                     } catch (final BackingStoreException ignored) {
 920                     }
 921                     return p;
 922                 });
 923     }
 924 
 925     @Override
 926     public AudioSynthesizerPropertyInfo[] getPropertyInfo(Map<String, Object> info) {
 927         List<AudioSynthesizerPropertyInfo> list = new ArrayList<>();

 928 
 929         AudioSynthesizerPropertyInfo item;
 930 
 931         // If info != null or synthesizer is closed
 932         //   we return how the synthesizer will be set on next open
 933         // If info == null and synthesizer is open
 934         //   we return current synthesizer properties.
 935         boolean o = info == null && open;
 936 
 937         item = new AudioSynthesizerPropertyInfo("interpolation", o?resamplerType:"linear");
 938         item.choices = new String[]{"linear", "linear1", "linear2", "cubic",
 939                                     "lanczos", "sinc", "point"};
 940         item.description = "Interpolation method";
 941         list.add(item);
 942 
 943         item = new AudioSynthesizerPropertyInfo("control rate", o?controlrate:147f);
 944         item.description = "Control rate";
 945         list.add(item);
 946 
 947         item = new AudioSynthesizerPropertyInfo("format",


1062                     Number n = (Number) v;
1063                     if (c == Byte.class)
1064                         item2.value = Byte.valueOf(n.byteValue());
1065                     if (c == Short.class)
1066                         item2.value = Short.valueOf(n.shortValue());
1067                     if (c == Integer.class)
1068                         item2.value = Integer.valueOf(n.intValue());
1069                     if (c == Long.class)
1070                         item2.value = Long.valueOf(n.longValue());
1071                     if (c == Float.class)
1072                         item2.value = Float.valueOf(n.floatValue());
1073                     if (c == Double.class)
1074                         item2.value = Double.valueOf(n.doubleValue());
1075                 }
1076             }
1077         }
1078 
1079         return items;
1080     }
1081 
1082     @Override
1083     public void open() throws MidiUnavailableException {
1084         if (isOpen()) {
1085             synchronized (control_mutex) {
1086                 implicitOpen = false;
1087             }
1088             return;
1089         }
1090         open(null, null);
1091     }
1092 
1093     @Override
1094     public void open(SourceDataLine line, Map<String, Object> info) throws MidiUnavailableException {
1095         if (isOpen()) {
1096             synchronized (control_mutex) {
1097                 implicitOpen = false;
1098             }
1099             return;
1100         }
1101         synchronized (control_mutex) {
1102             try {
1103                 if (line != null) {
1104                     // can throw IllegalArgumentException
1105                     setFormat(line.getFormat());
1106                 }
1107 
1108                 AudioInputStream ais = openStream(getFormat(), info);
1109 
1110                 weakstream = new WeakAudioStream(ais);
1111                 ais = weakstream.getAudioInputStream();
1112 
1113                 if (line == null)


1168                 if(weakstream != null)
1169                 {
1170                     weakstream.pusher = pusher;
1171                     weakstream.sourceDataLine = sourceDataLine;
1172                 }
1173 
1174             } catch (final LineUnavailableException | SecurityException
1175                     | IllegalArgumentException e) {
1176                 if (isOpen()) {
1177                     close();
1178                 }
1179                 // am: need MidiUnavailableException(Throwable) ctor!
1180                 MidiUnavailableException ex = new MidiUnavailableException(
1181                         "Can not open line");
1182                 ex.initCause(e);
1183                 throw ex;
1184             }
1185         }
1186     }
1187 
1188     @Override
1189     public AudioInputStream openStream(AudioFormat targetFormat,
1190                                        Map<String, Object> info) throws MidiUnavailableException {
1191 
1192         if (isOpen())
1193             throw new MidiUnavailableException("Synthesizer is already open");
1194 
1195         synchronized (control_mutex) {
1196 
1197             gmmode = 0;
1198             voice_allocation_mode = 0;
1199 
1200             processPropertyInfo(info);
1201 
1202             open = true;
1203             implicitOpen = false;
1204 
1205             if (targetFormat != null)
1206                 setFormat(targetFormat);
1207 
1208             if (load_default_soundbank)


1250                 }
1251             }
1252 
1253             for (int i = 0; i < channels.length; i++)
1254                 external_channels[i].setChannel(channels[i]);
1255 
1256             for (SoftVoice voice: getVoices())
1257                 voice.resampler = resampler.openStreamer();
1258 
1259             for (Receiver recv: getReceivers()) {
1260                 SoftReceiver srecv = ((SoftReceiver)recv);
1261                 srecv.open = open;
1262                 srecv.mainmixer = mainmixer;
1263                 srecv.midimessages = mainmixer.midimessages;
1264             }
1265 
1266             return mainmixer.getInputStream();
1267         }
1268     }
1269 
1270     @Override
1271     public void close() {
1272 
1273         if (!isOpen())
1274             return;
1275 
1276         SoftAudioPusher pusher_to_be_closed = null;
1277         AudioInputStream pusher_stream_to_be_closed = null;
1278         synchronized (control_mutex) {
1279             if (pusher != null) {
1280                 pusher_to_be_closed = pusher;
1281                 pusher_stream_to_be_closed = pusher_stream;
1282                 pusher = null;
1283                 pusher_stream = null;
1284             }
1285         }
1286 
1287         if (pusher_to_be_closed != null) {
1288             // Pusher must not be closed synchronized against control_mutex,
1289             // this may result in synchronized conflict between pusher
1290             // and current thread.


1309 
1310             if (external_channels != null)
1311                 for (int i = 0; i < external_channels.length; i++)
1312                     external_channels[i].setChannel(null);
1313 
1314             if (sourceDataLine != null) {
1315                 sourceDataLine.close();
1316                 sourceDataLine = null;
1317             }
1318 
1319             inslist.clear();
1320             loadedlist.clear();
1321             tunings.clear();
1322 
1323             while (recvslist.size() != 0)
1324                 recvslist.get(recvslist.size() - 1).close();
1325 
1326         }
1327     }
1328 
1329     @Override
1330     public boolean isOpen() {
1331         synchronized (control_mutex) {
1332             return open;
1333         }
1334     }
1335 
1336     @Override
1337     public long getMicrosecondPosition() {
1338 
1339         if (!isOpen())
1340             return 0;
1341 
1342         synchronized (control_mutex) {
1343             return mainmixer.getMicrosecondPosition();
1344         }
1345     }
1346 
1347     @Override
1348     public int getMaxReceivers() {
1349         return -1;
1350     }
1351 
1352     @Override
1353     public int getMaxTransmitters() {
1354         return 0;
1355     }
1356 
1357     @Override
1358     public Receiver getReceiver() throws MidiUnavailableException {
1359 
1360         synchronized (control_mutex) {
1361             SoftReceiver receiver = new SoftReceiver(this);
1362             receiver.open = open;
1363             recvslist.add(receiver);
1364             return receiver;
1365         }
1366     }
1367 
1368     @Override
1369     public List<Receiver> getReceivers() {
1370 
1371         synchronized (control_mutex) {
1372             ArrayList<Receiver> recvs = new ArrayList<>();
1373             recvs.addAll(recvslist);
1374             return recvs;
1375         }
1376     }
1377 
1378     @Override
1379     public Transmitter getTransmitter() throws MidiUnavailableException {
1380 
1381         throw new MidiUnavailableException("No transmitter available");
1382     }
1383 
1384     @Override
1385     public List<Transmitter> getTransmitters() {
1386 
1387         return new ArrayList<>();
1388     }
1389 
1390     @Override
1391     public Receiver getReceiverReferenceCounting()
1392             throws MidiUnavailableException {
1393 
1394         if (!isOpen()) {
1395             open();
1396             synchronized (control_mutex) {
1397                 implicitOpen = true;
1398             }
1399         }
1400 
1401         return getReceiver();
1402     }
1403 
1404     @Override
1405     public Transmitter getTransmitterReferenceCounting()
1406             throws MidiUnavailableException {
1407 
1408         throw new MidiUnavailableException("No transmitter available");
1409     }
1410 }
< prev index next >