New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Audio API #1974
Add Audio API #1974
Conversation
* @param bigEndian whether the data is stored in big-endian or little-endian order. | ||
* @return a float array. | ||
*/ | ||
public static float[] fromByteArray(byte[] bytes, boolean bigEndian) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public static float[] fromByteArray(byte[] bytes, boolean bigEndian) { | |
public static float[] fromByteArray(byte[] bytes, ByteOrder endian) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
||
private static final Logger logger = LoggerFactory.getLogger(AudioFactory.class); | ||
|
||
@SuppressWarnings({"PMD.DoubleBraceInitialization", "PMD.UseConcurrentHashMap"}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
better avoid create a new anonymous class, you can use a static initializer instead.
This can be just a String[], no need use a map here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
* @return {@link AudioFactory} | ||
*/ | ||
public static AudioFactory newInstance(Configuration conf) { | ||
boolean android = "http://www.android.com/".equals(System.getProperty("java.vendor.url")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should just a simple try and fail approach for both Android and PC
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
* @param conf The configuration for {@link AudioFactory} to use. | ||
* @return {@link AudioFactory} | ||
*/ | ||
public static AudioFactory newInstance(Configuration conf) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need newInstace()
overload
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
* {@code Audio} is a container of an audio in DJL. The raw data of the audio is wrapped in a float | ||
* array. | ||
*/ | ||
public interface Audio { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Audio is just a data holder now. I'm not sure if we need a interface now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
* @param type type of the audio, such as "wav" | ||
* @throws IOException audio cannot be saved through output stream | ||
*/ | ||
void save(OutputStream os, String type) throws IOException; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let remove this since we didn't have any implementation now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
||
/** {@inheritDoc} */ | ||
@Override | ||
public void save(OutputStream os, String type) throws IOException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can move save
into Factory in needed in future
* @return the bytes read from the audio input stream. | ||
* @throws IOException if an input or output error occurs | ||
*/ | ||
public static byte[] read(AudioInputStream ais) throws IOException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this implementation in SampleAudioFactory?
int i = 0; | ||
for (Float f : list) { | ||
floatArray[i++] = (f != null ? f : Float.NaN); | ||
for (int i = 0; i < list.size(); i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think old one is better:
- doesn't need to call list.size() every thime
- it works better on non-randomaccess lists (Like LinkedList)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
* @return the float array read from the audio. | ||
* @throws FFmpegFrameGrabber.Exception if error occurs | ||
*/ | ||
public static float[] grab(FFmpegFrameGrabber grabber) throws FFmpegFrameGrabber.Exception { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be in FFmpegAudioFactory
Codecov Report
@@ Coverage Diff @@
## master #1974 +/- ##
============================================
- Coverage 72.08% 70.14% -1.94%
- Complexity 5126 5859 +733
============================================
Files 473 578 +105
Lines 21970 25946 +3976
Branches 2351 2795 +444
============================================
+ Hits 15838 18201 +2363
- Misses 4925 6373 +1448
- Partials 1207 1372 +165
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
} | ||
|
||
/** | ||
* Create new instance of audio factory from the provided factory implementation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Create new instance of audio factory from the provided factory implementation. | |
* Creates new instance of audio factory from the provided factory implementation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
} | ||
|
||
/** | ||
* Gets {@link Audio} from file. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Gets {@link Audio} from file. | |
* Returns {@link Audio} from file. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
} | ||
|
||
/** | ||
* Construct a new {@code Configuration} instance. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Construct a new {@code Configuration} instance. | |
* Constructs a new {@code Configuration} instance. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
public static final class Configuration { | ||
|
||
/** Default sample rate. */ | ||
public static final int DEFAULT_SAMPLE_RATE = 16000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this need to be public?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to private.
} | ||
|
||
/** | ||
* Get the number of channels of an audio file. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Get the number of channels of an audio file. | |
* Returns the number of channels of an audio file. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
} | ||
|
||
/** | ||
* Set the number of channels for {@link AudioFactory} to use. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Set the number of channels for {@link AudioFactory} to use. | |
* Sets the number of channels for {@link AudioFactory} to use. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
* @param endian whether the data is stored in big-endian or little-endian order. | ||
* @return a float array. | ||
*/ | ||
public static float[] fromByteArray(byte[] bytes, boolean endian) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public static float[] fromByteArray(byte[] bytes, boolean endian) { | |
public static float[] fromByteArray(byte[] bytes, ByteOrder endian) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There actually 3 endian type:
BIG, LITTLE and NATIVE
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html#order-java.nio.ByteOrder-
bo - The new byte order, either BIG_ENDIAN or LITTLE_ENDIAN.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NATIVE is actually BIG_ENDIAN or LITTLE_ENDIAN
Also I got whether it's big-endian or little-endian from AudioFormat, so there's no native involved.
float[] floats = Float16Utils.fromByteArray(bytes, format.isBigEndian());
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can choose to only pass in BIG/LITTLE to this API in AudioFactory, but the API should be able to accept any endian. The source of the input to this API may not only come from AudioSystem
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
05d30f5
to
cf6e419
Compare
Can you add some unit test? |
509b309
to
63c681e
Compare
Done |
* @param order the byte order to use. | ||
* @return a float array. | ||
*/ | ||
public static float[] fromByteArray(byte[] bytes, ByteOrder order) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm actually not sure if this really belongs to here,
return the value between -1.0f - 1.0f seems not general enough, it might only work for specific audio data processing use case.
Maybe we should keep this in AudioUtils.java
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can move it to SampledAudioFactory
|
||
public class AudioFactoryTest { | ||
|
||
private static final String PATH = "src/test/resources/speech.wav"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we re-use test-01.wav?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is test-01.wav?
|
||
@BeforeTest | ||
public void setUp() { | ||
factory = AudioFactory.getInstance(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doesn't really need a setup()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
||
@Test | ||
public void testFromInputStream() throws IOException { | ||
try (InputStream is = new BufferedInputStream(Files.newInputStream(Paths.get(PATH)))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does BufferedInputStream required? If true, we need add this in our API
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes BufferedInputStream is needed. I have added it to API.
5c60497
to
8f110cf
Compare
Change-Id: Ibcd61d71c17881afc46b01abcf4f14c7b5341d15
Change-Id: Id4750f56f937cbee7e80287be8f79396aec710cf
Description
Brief description of what this PR is about
Add Audio API