jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatFormatConverter.java
changeset 40444 afabcfc2f3ef
parent 35684 900e28dae561
child 41772 f26d4b69228b
equal deleted inserted replaced
40442:e97e9982be6d 40444:afabcfc2f3ef
    30 import java.util.ArrayList;
    30 import java.util.ArrayList;
    31 import java.util.Arrays;
    31 import java.util.Arrays;
    32 import java.util.Objects;
    32 import java.util.Objects;
    33 
    33 
    34 import javax.sound.sampled.AudioFormat;
    34 import javax.sound.sampled.AudioFormat;
       
    35 import javax.sound.sampled.AudioFormat.Encoding;
    35 import javax.sound.sampled.AudioInputStream;
    36 import javax.sound.sampled.AudioInputStream;
    36 import javax.sound.sampled.AudioSystem;
    37 import javax.sound.sampled.AudioSystem;
    37 import javax.sound.sampled.AudioFormat.Encoding;
       
    38 import javax.sound.sampled.spi.FormatConversionProvider;
    38 import javax.sound.sampled.spi.FormatConversionProvider;
    39 
    39 
    40 /**
    40 /**
    41  * This class is used to convert between 8,16,24,32 bit signed/unsigned
    41  * This class is used to convert between 8,16,24,32 bit signed/unsigned
    42  * big/litle endian fixed/floating stereo/mono/multi-channel audio streams and
    42  * big/litle endian fixed/floating stereo/mono/multi-channel audio streams and
    61             this.stream = stream;
    61             this.stream = stream;
    62             converter = AudioFloatConverter.getConverter(targetFormat);
    62             converter = AudioFloatConverter.getConverter(targetFormat);
    63             fsize = ((targetFormat.getSampleSizeInBits() + 7) / 8);
    63             fsize = ((targetFormat.getSampleSizeInBits() + 7) / 8);
    64         }
    64         }
    65 
    65 
       
    66         @Override
    66         public int read() throws IOException {
    67         public int read() throws IOException {
    67             byte[] b = new byte[1];
    68             byte[] b = new byte[1];
    68             int ret = read(b);
    69             int ret = read(b);
    69             if (ret < 0)
    70             if (ret < 0)
    70                 return ret;
    71                 return ret;
    71             return b[0] & 0xFF;
    72             return b[0] & 0xFF;
    72         }
    73         }
    73 
    74 
       
    75         @Override
    74         public int read(byte[] b, int off, int len) throws IOException {
    76         public int read(byte[] b, int off, int len) throws IOException {
    75 
    77 
    76             int flen = len / fsize;
    78             int flen = len / fsize;
    77             if (readfloatbuffer == null || readfloatbuffer.length < flen)
    79             if (readfloatbuffer == null || readfloatbuffer.length < flen)
    78                 readfloatbuffer = new float[flen];
    80                 readfloatbuffer = new float[flen];
    81                 return ret;
    83                 return ret;
    82             converter.toByteArray(readfloatbuffer, 0, ret, b, off);
    84             converter.toByteArray(readfloatbuffer, 0, ret, b, off);
    83             return ret * fsize;
    85             return ret * fsize;
    84         }
    86         }
    85 
    87 
       
    88         @Override
    86         public int available() throws IOException {
    89         public int available() throws IOException {
    87             int ret = stream.available();
    90             int ret = stream.available();
    88             if (ret < 0)
    91             if (ret < 0)
    89                 return ret;
    92                 return ret;
    90             return ret * fsize;
    93             return ret * fsize;
    91         }
    94         }
    92 
    95 
       
    96         @Override
    93         public void close() throws IOException {
    97         public void close() throws IOException {
    94             stream.close();
    98             stream.close();
    95         }
    99         }
    96 
   100 
       
   101         @Override
    97         public synchronized void mark(int readlimit) {
   102         public synchronized void mark(int readlimit) {
    98             stream.mark(readlimit * fsize);
   103             stream.mark(readlimit * fsize);
    99         }
   104         }
   100 
   105 
       
   106         @Override
   101         public boolean markSupported() {
   107         public boolean markSupported() {
   102             return stream.markSupported();
   108             return stream.markSupported();
   103         }
   109         }
   104 
   110 
       
   111         @Override
   105         public synchronized void reset() throws IOException {
   112         public synchronized void reset() throws IOException {
   106             stream.reset();
   113             stream.reset();
   107         }
   114         }
   108 
   115 
       
   116         @Override
   109         public long skip(long n) throws IOException {
   117         public long skip(long n) throws IOException {
   110             long ret = stream.skip(n / fsize);
   118             long ret = stream.skip(n / fsize);
   111             if (ret < 0)
   119             if (ret < 0)
   112                 return ret;
   120                 return ret;
   113             return ret * fsize;
   121             return ret * fsize;
   139                     targetChannels, (format.getFrameSize() / sourceChannels)
   147                     targetChannels, (format.getFrameSize() / sourceChannels)
   140                             * targetChannels, format.getFrameRate(), format
   148                             * targetChannels, format.getFrameRate(), format
   141                             .isBigEndian());
   149                             .isBigEndian());
   142         }
   150         }
   143 
   151 
       
   152         @Override
   144         public int available() throws IOException {
   153         public int available() throws IOException {
   145             return (ais.available() / sourceChannels) * targetChannels;
   154             return (ais.available() / sourceChannels) * targetChannels;
   146         }
   155         }
   147 
   156 
       
   157         @Override
   148         public void close() throws IOException {
   158         public void close() throws IOException {
   149             ais.close();
   159             ais.close();
   150         }
   160         }
   151 
   161 
       
   162         @Override
   152         public AudioFormat getFormat() {
   163         public AudioFormat getFormat() {
   153             return targetFormat;
   164             return targetFormat;
   154         }
   165         }
   155 
   166 
       
   167         @Override
   156         public long getFrameLength() {
   168         public long getFrameLength() {
   157             return ais.getFrameLength();
   169             return ais.getFrameLength();
   158         }
   170         }
   159 
   171 
       
   172         @Override
   160         public void mark(int readlimit) {
   173         public void mark(int readlimit) {
   161             ais.mark((readlimit / targetChannels) * sourceChannels);
   174             ais.mark((readlimit / targetChannels) * sourceChannels);
   162         }
   175         }
   163 
   176 
       
   177         @Override
   164         public boolean markSupported() {
   178         public boolean markSupported() {
   165             return ais.markSupported();
   179             return ais.markSupported();
   166         }
   180         }
   167 
   181 
       
   182         @Override
   168         public int read(float[] b, int off, int len) throws IOException {
   183         public int read(float[] b, int off, int len) throws IOException {
   169             int len2 = (len / targetChannels) * sourceChannels;
   184             int len2 = (len / targetChannels) * sourceChannels;
   170             if (conversion_buffer == null || conversion_buffer.length < len2)
   185             if (conversion_buffer == null || conversion_buffer.length < len2)
   171                 conversion_buffer = new float[len2];
   186                 conversion_buffer = new float[len2];
   172             int ret = ais.read(conversion_buffer, 0, len2);
   187             int ret = ais.read(conversion_buffer, 0, len2);
   210                 }
   225                 }
   211             }
   226             }
   212             return (ret / sourceChannels) * targetChannels;
   227             return (ret / sourceChannels) * targetChannels;
   213         }
   228         }
   214 
   229 
       
   230         @Override
   215         public void reset() throws IOException {
   231         public void reset() throws IOException {
   216             ais.reset();
   232             ais.reset();
   217         }
   233         }
   218 
   234 
       
   235         @Override
   219         public long skip(long len) throws IOException {
   236         public long skip(long len) throws IOException {
   220             long ret = ais.skip((len / targetChannels) * sourceChannels);
   237             long ret = ais.skip((len / targetChannels) * sourceChannels);
   221             if (ret < 0)
   238             if (ret < 0)
   222                 return ret;
   239                 return ret;
   223             return (ret / sourceChannels) * targetChannels;
   240             return (ret / sourceChannels) * targetChannels;
   303             ibuffer2 = new float[nrofchannels * buffer_len];
   320             ibuffer2 = new float[nrofchannels * buffer_len];
   304             ibuffer_index = buffer_len + pad;
   321             ibuffer_index = buffer_len + pad;
   305             ibuffer_len = buffer_len;
   322             ibuffer_len = buffer_len;
   306         }
   323         }
   307 
   324 
       
   325         @Override
   308         public int available() throws IOException {
   326         public int available() throws IOException {
   309             return 0;
   327             return 0;
   310         }
   328         }
   311 
   329 
       
   330         @Override
   312         public void close() throws IOException {
   331         public void close() throws IOException {
   313             ais.close();
   332             ais.close();
   314         }
   333         }
   315 
   334 
       
   335         @Override
   316         public AudioFormat getFormat() {
   336         public AudioFormat getFormat() {
   317             return targetFormat;
   337             return targetFormat;
   318         }
   338         }
   319 
   339 
       
   340         @Override
   320         public long getFrameLength() {
   341         public long getFrameLength() {
   321             return AudioSystem.NOT_SPECIFIED; // ais.getFrameLength();
   342             return AudioSystem.NOT_SPECIFIED; // ais.getFrameLength();
   322         }
   343         }
   323 
   344 
       
   345         @Override
   324         public void mark(int readlimit) {
   346         public void mark(int readlimit) {
   325             ais.mark((int) (readlimit * pitch[0]));
   347             ais.mark((int) (readlimit * pitch[0]));
   326             mark_ibuffer_index = ibuffer_index;
   348             mark_ibuffer_index = ibuffer_index;
   327             mark_ibuffer_len = ibuffer_len;
   349             mark_ibuffer_len = ibuffer_len;
   328             if (mark_ibuffer == null) {
   350             if (mark_ibuffer == null) {
   335                     to[i] = from[i];
   357                     to[i] = from[i];
   336                 }
   358                 }
   337             }
   359             }
   338         }
   360         }
   339 
   361 
       
   362         @Override
   340         public boolean markSupported() {
   363         public boolean markSupported() {
   341             return ais.markSupported();
   364             return ais.markSupported();
   342         }
   365         }
   343 
   366 
   344         private void readNextBuffer() throws IOException {
   367         private void readNextBuffer() throws IOException {
   379                 }
   402                 }
   380             }
   403             }
   381 
   404 
   382         }
   405         }
   383 
   406 
       
   407         @Override
   384         public int read(float[] b, int off, int len) throws IOException {
   408         public int read(float[] b, int off, int len) throws IOException {
   385 
   409 
   386             if (cbuffer == null || cbuffer[0].length < len / nrofchannels) {
   410             if (cbuffer == null || cbuffer[0].length < len / nrofchannels) {
   387                 cbuffer = new float[nrofchannels][len / nrofchannels];
   411                 cbuffer = new float[nrofchannels][len / nrofchannels];
   388             }
   412             }
   429                 }
   453                 }
   430             }
   454             }
   431             return len - remain * nrofchannels;
   455             return len - remain * nrofchannels;
   432         }
   456         }
   433 
   457 
       
   458         @Override
   434         public void reset() throws IOException {
   459         public void reset() throws IOException {
   435             ais.reset();
   460             ais.reset();
   436             if (mark_ibuffer == null)
   461             if (mark_ibuffer == null)
   437                 return;
   462                 return;
   438             ibuffer_index = mark_ibuffer_index;
   463             ibuffer_index = mark_ibuffer_index;
   445                 }
   470                 }
   446             }
   471             }
   447 
   472 
   448         }
   473         }
   449 
   474 
       
   475         @Override
   450         public long skip(long len) throws IOException {
   476         public long skip(long len) throws IOException {
   451             if (len < 0)
   477             if (len < 0)
   452                 return 0;
   478                 return 0;
   453             if (skipbuffer == null)
   479             if (skipbuffer == null)
   454                 skipbuffer = new float[1024 * targetFormat.getFrameSize()];
   480                 skipbuffer = new float[1024 * targetFormat.getFrameSize()];
   472 
   498 
   473     private final Encoding[] formats = {Encoding.PCM_SIGNED,
   499     private final Encoding[] formats = {Encoding.PCM_SIGNED,
   474                                         Encoding.PCM_UNSIGNED,
   500                                         Encoding.PCM_UNSIGNED,
   475                                         Encoding.PCM_FLOAT};
   501                                         Encoding.PCM_FLOAT};
   476 
   502 
       
   503     @Override
   477     public AudioInputStream getAudioInputStream(Encoding targetEncoding,
   504     public AudioInputStream getAudioInputStream(Encoding targetEncoding,
   478             AudioInputStream sourceStream) {
   505                                                 AudioInputStream sourceStream) {
   479         if (!isConversionSupported(targetEncoding, sourceStream.getFormat())) {
   506         if (!isConversionSupported(targetEncoding, sourceStream.getFormat())) {
   480             throw new IllegalArgumentException(
   507             throw new IllegalArgumentException(
   481                     "Unsupported conversion: " + sourceStream.getFormat()
   508                     "Unsupported conversion: " + sourceStream.getFormat()
   482                             .toString() + " to " + targetEncoding.toString());
   509                             .toString() + " to " + targetEncoding.toString());
   483         }
   510         }
   494         AudioFormat targetFormat = new AudioFormat(encoding, samplerate, bits,
   521         AudioFormat targetFormat = new AudioFormat(encoding, samplerate, bits,
   495                 channels, channels * bits / 8, samplerate, bigendian);
   522                 channels, channels * bits / 8, samplerate, bigendian);
   496         return getAudioInputStream(targetFormat, sourceStream);
   523         return getAudioInputStream(targetFormat, sourceStream);
   497     }
   524     }
   498 
   525 
       
   526     @Override
   499     public AudioInputStream getAudioInputStream(AudioFormat targetFormat,
   527     public AudioInputStream getAudioInputStream(AudioFormat targetFormat,
   500             AudioInputStream sourceStream) {
   528                                                 AudioInputStream sourceStream) {
   501         if (!isConversionSupported(targetFormat, sourceStream.getFormat()))
   529         if (!isConversionSupported(targetFormat, sourceStream.getFormat()))
   502             throw new IllegalArgumentException("Unsupported conversion: "
   530             throw new IllegalArgumentException("Unsupported conversion: "
   503                     + sourceStream.getFormat().toString() + " to "
   531                     + sourceStream.getFormat().toString() + " to "
   504                     + targetFormat.toString());
   532                     + targetFormat.toString());
   505         return getAudioInputStream(targetFormat, AudioFloatInputStream
   533         return getAudioInputStream(targetFormat, AudioFloatInputStream
   524         return new AudioInputStream(new AudioFloatFormatConverterInputStream(
   552         return new AudioInputStream(new AudioFloatFormatConverterInputStream(
   525                 targetFormat, sourceStream), targetFormat, sourceStream
   553                 targetFormat, sourceStream), targetFormat, sourceStream
   526                 .getFrameLength());
   554                 .getFrameLength());
   527     }
   555     }
   528 
   556 
       
   557     @Override
   529     public Encoding[] getSourceEncodings() {
   558     public Encoding[] getSourceEncodings() {
   530         return new Encoding[] { Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED,
   559         return new Encoding[] { Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED,
   531                 Encoding.PCM_FLOAT };
   560                 Encoding.PCM_FLOAT };
   532     }
   561     }
   533 
   562 
       
   563     @Override
   534     public Encoding[] getTargetEncodings() {
   564     public Encoding[] getTargetEncodings() {
   535         return new Encoding[] { Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED,
   565         return new Encoding[] { Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED,
   536                 Encoding.PCM_FLOAT };
   566                 Encoding.PCM_FLOAT };
   537     }
   567     }
   538 
   568 
       
   569     @Override
   539     public Encoding[] getTargetEncodings(AudioFormat sourceFormat) {
   570     public Encoding[] getTargetEncodings(AudioFormat sourceFormat) {
   540         if (AudioFloatConverter.getConverter(sourceFormat) == null)
   571         if (AudioFloatConverter.getConverter(sourceFormat) == null)
   541             return new Encoding[0];
   572             return new Encoding[0];
   542         return new Encoding[] { Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED,
   573         return new Encoding[] { Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED,
   543                 Encoding.PCM_FLOAT };
   574                 Encoding.PCM_FLOAT };
   544     }
   575     }
   545 
   576 
       
   577     @Override
   546     public AudioFormat[] getTargetFormats(Encoding targetEncoding,
   578     public AudioFormat[] getTargetFormats(Encoding targetEncoding,
   547             AudioFormat sourceFormat) {
   579                                           AudioFormat sourceFormat) {
   548         Objects.requireNonNull(targetEncoding);
   580         Objects.requireNonNull(targetEncoding);
   549         if (AudioFloatConverter.getConverter(sourceFormat) == null)
   581         if (AudioFloatConverter.getConverter(sourceFormat) == null)
   550             return new AudioFormat[0];
   582             return new AudioFormat[0];
   551         int channels = sourceFormat.getChannels();
   583         int channels = sourceFormat.getChannels();
   552 
   584 
   553         ArrayList<AudioFormat> formats = new ArrayList<AudioFormat>();
   585         ArrayList<AudioFormat> formats = new ArrayList<>();
   554 
   586 
   555         if (targetEncoding.equals(Encoding.PCM_SIGNED))
   587         if (targetEncoding.equals(Encoding.PCM_SIGNED))
   556             formats.add(new AudioFormat(Encoding.PCM_SIGNED,
   588             formats.add(new AudioFormat(Encoding.PCM_SIGNED,
   557                     AudioSystem.NOT_SPECIFIED, 8, channels, channels,
   589                     AudioSystem.NOT_SPECIFIED, 8, channels, channels,
   558                     AudioSystem.NOT_SPECIFIED, false));
   590                     AudioSystem.NOT_SPECIFIED, false));
   596         }
   628         }
   597 
   629 
   598         return formats.toArray(new AudioFormat[formats.size()]);
   630         return formats.toArray(new AudioFormat[formats.size()]);
   599     }
   631     }
   600 
   632 
       
   633     @Override
   601     public boolean isConversionSupported(AudioFormat targetFormat,
   634     public boolean isConversionSupported(AudioFormat targetFormat,
   602             AudioFormat sourceFormat) {
   635                                          AudioFormat sourceFormat) {
   603         Objects.requireNonNull(targetFormat);
   636         Objects.requireNonNull(targetFormat);
   604         if (AudioFloatConverter.getConverter(sourceFormat) == null)
   637         if (AudioFloatConverter.getConverter(sourceFormat) == null)
   605             return false;
   638             return false;
   606         if (AudioFloatConverter.getConverter(targetFormat) == null)
   639         if (AudioFloatConverter.getConverter(targetFormat) == null)
   607             return false;
   640             return false;
   610         if (targetFormat.getChannels() <= 0)
   643         if (targetFormat.getChannels() <= 0)
   611             return false;
   644             return false;
   612         return true;
   645         return true;
   613     }
   646     }
   614 
   647 
       
   648     @Override
   615     public boolean isConversionSupported(Encoding targetEncoding,
   649     public boolean isConversionSupported(Encoding targetEncoding,
   616             AudioFormat sourceFormat) {
   650                                          AudioFormat sourceFormat) {
   617         Objects.requireNonNull(targetEncoding);
   651         Objects.requireNonNull(targetEncoding);
   618         if (AudioFloatConverter.getConverter(sourceFormat) == null)
   652         if (AudioFloatConverter.getConverter(sourceFormat) == null)
   619             return false;
   653             return false;
   620         for (int i = 0; i < formats.length; i++) {
   654         for (int i = 0; i < formats.length; i++) {
   621             if (targetEncoding.equals(formats[i]))
   655             if (targetEncoding.equals(formats[i]))