AudioTrack.java revision b27f2d3126d68796925f96078fd5ab3eb466e98a
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.media.videoeditor;
18
19import java.io.IOException;
20
21/**
22 * This class allows to handle an audio track. This audio file is mixed with the
23 * audio samples of the MediaItems.
24 * {@hide}
25 */
26public class AudioTrack {
27    // Instance variables
28    private final String mUniqueId;
29    private final String mFilename;
30    private long mStartTimeMs;
31    private long mTimelineDurationMs;
32    private int mVolumePercent;
33    private long mBeginBoundaryTimeMs;
34    private long mEndBoundaryTimeMs;
35    private boolean mLoop;
36    private boolean mMuted;
37
38    private final long mDurationMs;
39    private final int mAudioChannels;
40    private final int mAudioType;
41    private final int mAudioBitrate;
42    private final int mAudioSamplingFrequency;
43
44    // Ducking variables
45    private int mDuckingThreshold;
46    private int mDuckingLowVolume;
47    private boolean mIsDuckingEnabled;
48
49    // The audio waveform filename
50    private String mAudioWaveformFilename;
51
52    /**
53     * An object of this type cannot be instantiated by using the default
54     * constructor
55     */
56    @SuppressWarnings("unused")
57    private AudioTrack() throws IOException {
58        this(null, null, null);
59    }
60
61    /**
62     * Constructor
63     *
64     * @param editor The video editor reference
65     * @param audioTrackId The audio track id
66     * @param filename The absolute file name
67     *
68     * @throws IOException if file is not found
69     * @throws IllegalArgumentException if file format is not supported or if
70     *             the codec is not supported
71     */
72    public AudioTrack(VideoEditor editor, String audioTrackId, String filename)
73            throws IOException {
74        mUniqueId = audioTrackId;
75        mFilename = filename;
76        mStartTimeMs = 0;
77        // TODO: This value represents to the duration of the audio file
78        mDurationMs = 300000;
79        // TODO: This value needs to be read from the audio track of the source
80        // file
81        mAudioChannels = 2;
82        mAudioType = MediaProperties.ACODEC_AAC_LC;
83        mAudioBitrate = 128000;
84        mAudioSamplingFrequency = 44100;
85
86        mTimelineDurationMs = mDurationMs;
87        mVolumePercent = 100;
88
89        // Play the entire audio track
90        mBeginBoundaryTimeMs = 0;
91        mEndBoundaryTimeMs = mDurationMs;
92
93        // By default loop is disabled
94        mLoop = false;
95
96        // By default the audio track is not muted
97        mMuted = false;
98
99        // Ducking is enabled by default
100        mDuckingThreshold = 0;
101        mDuckingLowVolume = 0;
102        mIsDuckingEnabled = true;
103
104        // The audio waveform file is generated later
105        mAudioWaveformFilename = null;
106    }
107
108    /**
109     * Constructor
110     *
111     * @param editor The video editor reference
112     * @param audioTrackId The audio track id
113     * @param filename The audio filename
114     * @param startTimeMs the start time in milliseconds (relative to the
115     *              timeline)
116     * @param beginMs start time in the audio track in milliseconds (relative to
117     *            the beginning of the audio track)
118     * @param endMs end time in the audio track in milliseconds (relative to the
119     *            beginning of the audio track)
120     * @param loop true to loop the audio track
121     * @param volume The volume in percentage
122     * @param muted true if the audio track is muted
123     * @param audioWaveformFilename The name of the waveform file
124     *
125     * @throws IOException if file is not found
126     */
127    AudioTrack(VideoEditor editor, String audioTrackId, String filename, long startTimeMs,
128            long beginMs, long endMs, boolean loop, int volume, boolean muted,
129            String audioWaveformFilename) throws IOException {
130        mUniqueId = audioTrackId;
131        mFilename = filename;
132        mStartTimeMs = startTimeMs;
133
134        // TODO: This value represents to the duration of the audio file
135        mDurationMs = 300000;
136
137        // TODO: This value needs to be read from the audio track of the source
138        // file
139        mAudioChannels = 2;
140        mAudioType = MediaProperties.ACODEC_AAC_LC;
141        mAudioBitrate = 128000;
142        mAudioSamplingFrequency = 44100;
143
144        mTimelineDurationMs = endMs - beginMs;
145        mVolumePercent = volume;
146
147        mBeginBoundaryTimeMs = beginMs;
148        mEndBoundaryTimeMs = endMs;
149
150        mLoop = loop;
151        mMuted = muted;
152
153        mAudioWaveformFilename = audioWaveformFilename;
154    }
155
156    /**
157     * @return The id of the audio track
158     */
159    public String getId() {
160        return mUniqueId;
161    }
162
163    /**
164     * Get the filename source for this audio track.
165     *
166     * @return The filename as an absolute file name
167     */
168    public String getFilename() {
169        return mFilename;
170    }
171
172    /**
173     * @return The number of audio channels in the source of this audio track
174     */
175    public int getAudioChannels() {
176        return mAudioChannels;
177    }
178
179    /**
180     * @return The audio codec of the source of this audio track
181     */
182    public int getAudioType() {
183        return mAudioType;
184    }
185
186    /**
187     * @return The audio sample frequency of the audio track
188     */
189    public int getAudioSamplingFrequency() {
190        return mAudioSamplingFrequency;
191    }
192
193    /**
194     * @return The audio bitrate of the audio track
195     */
196    public int getAudioBitrate() {
197        return mAudioBitrate;
198    }
199
200    /**
201     * Set the volume of this audio track as percentage of the volume in the
202     * original audio source file.
203     *
204     * @param volumePercent Percentage of the volume to apply. If it is set to
205     *            0, then volume becomes mute. It it is set to 100, then volume
206     *            is same as original volume. It it is set to 200, then volume
207     *            is doubled (provided that volume amplification is supported)
208     *
209     * @throws UnsupportedOperationException if volume amplification is
210     *             requested and is not supported.
211     */
212    public void setVolume(int volumePercent) {
213        mVolumePercent = volumePercent;
214    }
215
216    /**
217     * Get the volume of the audio track as percentage of the volume in the
218     * original audio source file.
219     *
220     * @return The volume in percentage
221     */
222    public int getVolume() {
223        return mVolumePercent;
224    }
225
226    /**
227     * @param muted true to mute the audio track
228     */
229    public void setMute(boolean muted) {
230        mMuted = muted;
231    }
232
233    /**
234     * @return true if the audio track is muted
235     */
236    public boolean isMuted() {
237        return mMuted;
238    }
239
240    /**
241     * Set the start time of this audio track relative to the storyboard
242     * timeline. Default value is 0.
243     *
244     * @param startTimeMs the start time in milliseconds
245     */
246    public void setStartTime(long startTimeMs) {
247        mStartTimeMs = startTimeMs;
248    }
249
250    /**
251     * Get the start time of this audio track relative to the storyboard
252     * timeline.
253     *
254     * @return The start time in milliseconds
255     */
256    public long getStartTime() {
257        return mStartTimeMs;
258    }
259
260    /**
261     * @return The duration in milliseconds. This value represents the audio
262     *         track duration (not looped)
263     */
264    public long getDuration() {
265        return mDurationMs;
266    }
267
268    /**
269     * @return The timeline duration. If looping is enabled this value
270     *         represents the duration of the looped audio track, otherwise it
271     *         is the duration of the audio track (mDurationMs).
272     */
273    public long getTimelineDuration() {
274        return mTimelineDurationMs;
275    }
276
277    /**
278     * Sets the start and end marks for trimming an audio track
279     *
280     * @param beginMs start time in the audio track in milliseconds (relative to
281     *            the beginning of the audio track)
282     * @param endMs end time in the audio track in milliseconds (relative to the
283     *            beginning of the audio track)
284     */
285    public void setExtractBoundaries(long beginMs, long endMs) {
286        if (beginMs > mDurationMs) {
287            throw new IllegalArgumentException("Invalid start time");
288        }
289        if (endMs > mDurationMs) {
290            throw new IllegalArgumentException("Invalid end time");
291        }
292
293        mBeginBoundaryTimeMs = beginMs;
294        mEndBoundaryTimeMs = endMs;
295        if (mLoop) {
296            // TODO: Compute mDurationMs (from the beginning of the loop until
297            // the end of all the loops.
298            mTimelineDurationMs = mEndBoundaryTimeMs - mBeginBoundaryTimeMs;
299        } else {
300            mTimelineDurationMs = mEndBoundaryTimeMs - mBeginBoundaryTimeMs;
301        }
302    }
303
304    /**
305     * @return The boundary begin time
306     */
307    public long getBoundaryBeginTime() {
308        return mBeginBoundaryTimeMs;
309    }
310
311    /**
312     * @return The boundary end time
313     */
314    public long getBoundaryEndTime() {
315        return mEndBoundaryTimeMs;
316    }
317
318    /**
319     * Enable the loop mode for this audio track. Note that only one of the
320     * audio tracks in the timeline can have the loop mode enabled. When looping
321     * is enabled the samples between mBeginBoundaryTimeMs and
322     * mEndBoundaryTimeMs are looped.
323     */
324    public void enableLoop() {
325        mLoop = true;
326    }
327
328    /**
329     * Disable the loop mode
330     */
331    public void disableLoop() {
332        mLoop = false;
333    }
334
335    /**
336     * @return true if looping is enabled
337     */
338    public boolean isLooping() {
339        return mLoop;
340    }
341
342    /**
343     * Disable the audio duck effect
344     */
345    public void disableDucking() {
346        mIsDuckingEnabled = false;
347    }
348
349    /**
350     * TODO DEFINE
351     *
352     * @param threshold
353     * @param lowVolume
354     * @param volume
355     */
356    public void enableDucking(int threshold, int lowVolume, int volume) {
357        mDuckingThreshold = threshold;
358        mDuckingLowVolume = lowVolume;
359        mIsDuckingEnabled = true;
360    }
361
362    /**
363     * @return true if ducking is enabled
364     */
365    public boolean isDuckingEnabled() {
366        return mIsDuckingEnabled;
367    }
368
369    /**
370     * @return The ducking threshold
371     */
372    public int getDuckingThreshhold() {
373        return mDuckingThreshold;
374    }
375
376    /**
377     * @return The ducking low level
378     */
379    public int getDuckingLowVolume() {
380        return mDuckingLowVolume;
381    }
382
383    /**
384     * This API allows to generate a file containing the sample volume levels of
385     * this audio track object. This function may take significant time and is
386     * blocking. The filename can be retrieved using getAudioWaveformFilename().
387     *
388     * @param listener The progress listener
389     *
390     * @throws IOException if the output file cannot be created
391     * @throws IllegalArgumentException if the audio file does not have a valid
392     *             audio track
393     */
394    public void extractAudioWaveform(ExtractAudioWaveformProgressListener listener)
395            throws IOException {
396        // TODO: Set mAudioWaveformFilename at the end once the extract is
397        // complete
398    }
399
400    /**
401     * Get the audio waveform file name if extractAudioWaveform was successful.
402     * The file format is as following:
403     * <ul>
404     * <li>first 4 bytes provide the number of samples for each value, as
405     * big-endian signed</li>
406     * <li>4 following bytes is the total number of values in the file, as
407     * big-endian signed</li>
408     * <li>then, all values follow as bytes</li>
409     * </ul>
410     *
411     * @return the name of the file, null if the file does not exist
412     */
413    public String getAudioWaveformFilename() {
414        return mAudioWaveformFilename;
415    }
416
417    /*
418     * {@inheritDoc}
419     */
420    @Override
421    public boolean equals(Object object) {
422        if (!(object instanceof AudioTrack)) {
423            return false;
424        }
425        return mUniqueId.equals(((AudioTrack)object).mUniqueId);
426    }
427
428    /*
429     * {@inheritDoc}
430     */
431    @Override
432    public int hashCode() {
433        return mUniqueId.hashCode();
434    }
435}
436