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 17 package com.android.videoeditor.service; 18 19 import java.io.IOException; 20 21 import android.media.videoeditor.AudioTrack; 22 import android.media.videoeditor.MediaProperties; 23 import android.media.videoeditor.VideoEditor; 24 import android.media.videoeditor.WaveformData; 25 26 /** 27 * This class represents an audio track in the user interface 28 */ 29 public class MovieAudioTrack { 30 // Instance variables 31 private final String mUniqueId; 32 private final String mFilename; 33 private final int mRawResourceId; 34 private final long mDurationMs; 35 private long mStartTimeMs; 36 private long mTimelineDurationMs; 37 private int mVolumePercent; 38 private boolean mMuted; 39 private long mBeginBoundaryTimeMs; 40 private long mEndBoundaryTimeMs; 41 private boolean mLoop; 42 43 private final int mAudioChannels; 44 private final int mAudioType; 45 private final int mAudioBitrate; 46 private final int mAudioSamplingFrequency; 47 48 // Ducking variables 49 private boolean mIsDuckingEnabled; 50 51 // The audio waveform data 52 private WaveformData mWaveformData; 53 54 private long mAppStartTimeMs; 55 private int mAppVolumePercent; 56 private boolean mAppMuted; 57 private boolean mAppIsDuckingEnabled; 58 private boolean mAppLoop; 59 60 /** 61 * An object of this type cannot be instantiated by using the default 62 * constructor 63 */ 64 @SuppressWarnings("unused") 65 private MovieAudioTrack() throws IOException { 66 this((AudioTrack)null); 67 } 68 69 /** 70 * Constructor 71 * 72 * @param audioTrack The audio track 73 */ 74 MovieAudioTrack(AudioTrack audioTrack) { 75 mUniqueId = audioTrack.getId(); 76 mFilename = audioTrack.getFilename(); 77 mRawResourceId = 0; 78 mAppStartTimeMs = mStartTimeMs = audioTrack.getStartTime(); 79 mDurationMs = audioTrack.getDuration(); 80 mBeginBoundaryTimeMs = audioTrack.getBoundaryBeginTime(); 81 mEndBoundaryTimeMs = audioTrack.getBoundaryEndTime(); 82 83 mAudioChannels = audioTrack.getAudioChannels(); 84 mAudioType = audioTrack.getAudioType(); 85 mAudioBitrate = audioTrack.getAudioBitrate(); 86 mAudioSamplingFrequency = audioTrack.getAudioSamplingFrequency(); 87 88 mAppVolumePercent = mVolumePercent = audioTrack.getVolume(); 89 mAppMuted = mMuted = audioTrack.isMuted(); 90 mAppLoop = mLoop = audioTrack.isLooping(); 91 92 mAppIsDuckingEnabled = mIsDuckingEnabled = audioTrack.isDuckingEnabled(); 93 94 try { 95 mWaveformData = audioTrack.getWaveformData(); 96 } catch (Exception ex) { 97 mWaveformData = null; 98 } 99 100 mTimelineDurationMs = mEndBoundaryTimeMs - mBeginBoundaryTimeMs; 101 } 102 103 /** 104 * Constructor 105 * 106 * @param resId The audio track raw resource id 107 */ 108 MovieAudioTrack(int resId) { 109 mUniqueId = null; 110 mFilename = null; 111 mRawResourceId = resId; 112 mAppStartTimeMs = mStartTimeMs = 0; 113 mDurationMs = VideoEditor.DURATION_OF_STORYBOARD; 114 mBeginBoundaryTimeMs = mStartTimeMs; 115 mEndBoundaryTimeMs = mDurationMs; 116 117 mAudioChannels = 0; 118 mAudioType = MediaProperties.ACODEC_AAC_LC; 119 mAudioBitrate = 0; 120 mAudioSamplingFrequency = 0; 121 122 mAppVolumePercent = mVolumePercent = 100; 123 mAppMuted = mMuted = false; 124 mAppLoop = mLoop = true; 125 126 mAppIsDuckingEnabled = mIsDuckingEnabled = true; 127 128 mWaveformData = null; 129 130 mTimelineDurationMs = mEndBoundaryTimeMs - mBeginBoundaryTimeMs; 131 } 132 133 /** 134 * @return The id of the media item 135 */ 136 public String getId() { 137 return mUniqueId; 138 } 139 140 /** 141 * @return The raw resource id 142 */ 143 public int getRawResourceId() { 144 return mRawResourceId; 145 } 146 147 /** 148 * Get the filename source for this audio track. 149 * 150 * @return The filename as an absolute file name 151 */ 152 public String getFilename() { 153 return mFilename; 154 } 155 156 /** 157 * @return The number of audio channels in the source of this audio track 158 */ 159 public int getAudioChannels() { 160 return mAudioChannels; 161 } 162 163 /** 164 * @return The audio codec of the source of this audio track 165 */ 166 public int getAudioType() { 167 return mAudioType; 168 } 169 170 /** 171 * @return The audio sample frequency of the audio track 172 */ 173 public int getAudioSamplingFrequency() { 174 return mAudioSamplingFrequency; 175 } 176 177 /** 178 * @return The audio bitrate of the audio track 179 */ 180 public int getAudioBitrate() { 181 return mAudioBitrate; 182 } 183 184 /** 185 * Set the volume of this audio track as percentage of the volume in the 186 * original audio source file. 187 * 188 * @param volumePercent Percentage of the volume to apply. If it is set to 189 * 0, then volume becomes mute. It it is set to 100, then volume 190 * is same as original volume. It it is set to 200, then volume 191 * is doubled (provided that volume amplification is supported) 192 * @throws UnsupportedOperationException if volume amplification is requested 193 * and is not supported. 194 */ 195 void setVolume(int volumePercent) { 196 mVolumePercent = volumePercent; 197 } 198 199 /** 200 * Get the volume of the audio track as percentage of the volume in the 201 * original audio source file. 202 * 203 * @return The volume in percentage 204 */ 205 int getVolume() { 206 return mVolumePercent; 207 } 208 209 /** 210 * Set the volume of this audio track as percentage of the volume in the 211 * original audio source file. 212 * 213 * @param volumePercent Percentage of the volume to apply. If it is set to 214 * 0, then volume becomes mute. It it is set to 100, then volume 215 * is same as original volume. It it is set to 200, then volume 216 * is doubled (provided that volume amplification is supported) 217 * @throws UnsupportedOperationException if volume amplification is requested 218 * and is not supported. 219 */ 220 public void setAppVolume(int volumePercent) { 221 mAppVolumePercent = volumePercent; 222 } 223 224 /** 225 * Get the volume of the audio track as percentage of the volume in the 226 * original audio source file. 227 * 228 * @return The volume in percentage 229 */ 230 public int getAppVolume() { 231 return mAppVolumePercent; 232 } 233 234 /** 235 * @param muted true to mute the audio track 236 */ 237 void setMute(boolean muted) { 238 mMuted = muted; 239 } 240 241 /** 242 * @return true if the audio track is muted 243 */ 244 boolean isMuted() { 245 return mMuted; 246 } 247 248 /** 249 * @param muted true to mute the audio track 250 */ 251 public void setAppMute(boolean muted) { 252 mAppMuted = muted; 253 } 254 255 /** 256 * @return true if the audio track is muted 257 */ 258 public boolean isAppMuted() { 259 return mAppMuted; 260 } 261 262 /** 263 * Set the start time of this audio track relative to the storyboard 264 * timeline. Default value is 0. 265 * 266 * @param startTimeMs the start time in milliseconds 267 */ 268 void setStartTime(long startTimeMs) { 269 mStartTimeMs = startTimeMs; 270 } 271 272 /** 273 * Get the start time of this audio track relative to the storyboard 274 * timeline. 275 * 276 * @return The start time in milliseconds 277 */ 278 public long getStartTime() { 279 return mStartTimeMs; 280 } 281 282 /** 283 * Set the start time of this audio track relative to the storyboard 284 * timeline. Default value is 0. 285 * 286 * @param startTimeMs the start time in milliseconds 287 */ 288 public void setAppStartTime(long startTimeMs) { 289 mAppStartTimeMs = startTimeMs; 290 } 291 292 /** 293 * Get the start time of this audio track relative to the storyboard 294 * timeline. 295 * 296 * @return The start time in milliseconds 297 */ 298 public long getAppStartTime() { 299 return mAppStartTimeMs; 300 } 301 302 /** 303 * @return The duration in milliseconds. This value represents the audio 304 * track duration (not looped) 305 */ 306 public long getDuration() { 307 return mDurationMs; 308 } 309 310 /** 311 * @return The timeline duration. 312 */ 313 public long getTimelineDuration() { 314 return mTimelineDurationMs; 315 } 316 317 /** 318 * Sets the start and end marks for trimming an audio track 319 * 320 * @param beginMs start time in the audio track in milliseconds (relative to 321 * the beginning of the audio track) 322 * @param endMs end time in the audio track in milliseconds (relative to the 323 * beginning of the audio track) 324 */ 325 void setExtractBoundaries(long beginMs, long endMs) { 326 mBeginBoundaryTimeMs = beginMs; 327 mEndBoundaryTimeMs = endMs; 328 mTimelineDurationMs = mEndBoundaryTimeMs - mBeginBoundaryTimeMs; 329 } 330 331 /** 332 * @return The boundary begin time 333 */ 334 public long getBoundaryBeginTime() { 335 return mBeginBoundaryTimeMs; 336 } 337 338 /** 339 * @return The boundary end time 340 */ 341 public long getBoundaryEndTime() { 342 return mEndBoundaryTimeMs; 343 } 344 345 /** 346 * Enable the loop mode for this audio track. Note that only one of the 347 * audio tracks in the timeline can have the loop mode enabled. When looping 348 * is enabled the samples between mBeginBoundaryTimeMs and 349 * mEndBoundaryTimeMs are looped. 350 * 351 * @param loop true to enable looping 352 */ 353 void enableLoop(boolean loop) { 354 mLoop = loop; 355 } 356 357 /** 358 * @return true if looping is enabled 359 */ 360 boolean isLooping() { 361 return mLoop; 362 } 363 364 /** 365 * Enable the loop mode for this audio track. Note that only one of the 366 * audio tracks in the timeline can have the loop mode enabled. When looping 367 * is enabled the samples between mBeginBoundaryTimeMs and 368 * mEndBoundaryTimeMs are looped. 369 * 370 * @param loop true to enable looping 371 */ 372 public void enableAppLoop(boolean loop) { 373 mAppLoop = loop; 374 } 375 376 /** 377 * @return true if looping is enabled 378 */ 379 public boolean isAppLooping() { 380 return mAppLoop; 381 } 382 383 /** 384 * Enable/disable ducking 385 * 386 * @param enabled true to enable ducking 387 */ 388 void enableDucking(boolean enabled) { 389 mIsDuckingEnabled = enabled; 390 } 391 392 /** 393 * @return true if ducking is enabled 394 */ 395 boolean isDuckingEnabled() { 396 return mIsDuckingEnabled; 397 } 398 399 /** 400 * Enable/disable ducking 401 * 402 * @param enabled true to enable ducking 403 */ 404 public void enableAppDucking(boolean enabled) { 405 mAppIsDuckingEnabled = enabled; 406 } 407 408 /** 409 * @return true if ducking is enabled 410 */ 411 public boolean isAppDuckingEnabled() { 412 return mAppIsDuckingEnabled; 413 } 414 415 /** 416 * @return The waveform data 417 */ 418 public WaveformData getWaveformData() { 419 return mWaveformData; 420 } 421 422 /** 423 * @param waveformData The audio waveform data 424 */ 425 void setWaveformData(WaveformData waveformData) { 426 mWaveformData = waveformData; 427 } 428 429 /* 430 * {@inheritDoc} 431 */ 432 @Override 433 public boolean equals(Object object) { 434 if (!(object instanceof MovieAudioTrack)) { 435 return false; 436 } 437 return mUniqueId.equals(((MovieAudioTrack)object).mUniqueId); 438 } 439 440 /* 441 * {@inheritDoc} 442 */ 443 @Override 444 public int hashCode() { 445 return mUniqueId.hashCode(); 446 } 447 } 448