Changeset 1561 for trunk/src/org/apollo
- Timestamp:
- 05/19/21 09:01:33 (3 years ago)
- Location:
- trunk/src/org/apollo
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/apollo/audio/util/SoundDesk.java
r1434 r1561 747 747 748 748 // Create the (new) track sequence to associate the mix with 749 // **** Look for TimeStretchFactor 750 // **** Apply 'factor' to generate new version of Audio (WAV file??) 751 // **** Feed to audio bytes from that into a TrackSequence 752 749 753 TrackSequence ts = new TrackSequence( 750 754 tmodel.getAllAudioBytes(), -
trunk/src/org/apollo/gui/PlaybackControlPopup.java
r1102 r1561 39 39 public JToggleButton muteButton; 40 40 public JToggleButton soloButton; 41 public JToggleButton beatDetectButton; 41 42 public JButton miscButton; 42 43 public JSlider volumeSlider; … … 100 101 }); 101 102 103 beatDetectButton = new JToggleButton(); 104 SwingMiscManager.setJButtonIcon(beatDetectButton,IconRepository.getIcon("beatDetect.png")); 105 SwingMiscManager.setJButtonSelectedIcon(beatDetectButton,IconRepository.getIcon("beatDetect-no-sticks.png")); 106 beatDetectButton.setPreferredSize(new Dimension(BUTTON_SIZE, BUTTON_SIZE)); 107 beatDetectButton.setToolTipText("Toggle beat detection in track"); 108 109 beatDetectButton.addChangeListener(new ChangeListener() { 110 public void stateChanged(ChangeEvent e) { 111 if (!PlaybackControlPopup.this.isUpdatingGUI) { 112 beatDetectChanged(); 113 } 114 } 115 }); 116 102 117 miscButton = new JButton(); 103 118 miscButton.addActionListener(this); … … 155 170 c.gridy = 0; 156 171 c.fill = GridBagConstraints.BOTH; 172 panel.add(beatDetectButton, c); 173 174 c = new GridBagConstraints(); 175 c.gridx = 6; 176 c.gridy = 0; 177 c.fill = GridBagConstraints.BOTH; 157 178 c.insets = new Insets(0,VOLUME_SPACING,0,VOLUME_SPACING); 158 179 panel.add(volumeSlider, c); 159 180 160 181 c = new GridBagConstraints(); 161 c.gridx = 7;182 c.gridx = 8; 162 183 c.gridy = 0; 163 184 c.fill = GridBagConstraints.BOTH; … … 211 232 // this.setSize(BUTTON_SIZE * 4, BUTTON_SIZE * 2); 212 233 213 panel.setSize(BUTTON_SIZE * 8, BUTTON_SIZE);234 panel.setSize(BUTTON_SIZE * 9, BUTTON_SIZE); 214 235 215 236 panel.doLayout(); … … 270 291 protected abstract void soloChanged(); 271 292 293 protected abstract void beatDetectChanged(); 294 272 295 273 296 /** -
trunk/src/org/apollo/gui/SampledTrackGraphView.java
r1102 r1561 70 70 private int timescaleFrameLength = 0; // in frames 71 71 72 private double timeStretchFactor = 1.0; 73 72 74 private final Font RENDER_MESSAGE_FONT = new Font("Arial", Font.BOLD | Font.ITALIC, 14); 73 75 … … 80 82 private Color backColorHighlights = DEFAULT_BACKGROUND_HIGHTLIGHTS_COLOR; 81 83 82 public static final Color PLAYBACK_BAR_COLOR = new Color(225, 187, 15); 84 public static final Color PLAYBACK_BAR_COLOR = new Color(225, 187, 15); // ****** 83 85 84 86 /** The stroke used for drawing graph bars. E.G: The selection Start bar. */ … … 546 548 } 547 549 550 551 public void setTimeStretchFactor(double time_stretch_factor) { 552 timeStretchFactor = time_stretch_factor; 553 } 554 555 public double getTimeStretchFactor() 556 { 557 return timeStretchFactor; 558 } 559 548 560 /** 549 561 * Re-renders the waveform buffers to match the graph size if it needs to. … … 623 635 trackModel.getAllAudioBytes(), 624 636 trackModel.getFormat(), 637 trackModel.getBeats(), 625 638 timescaleFrameStart, 626 639 timescaleFrameLength, … … 743 756 744 757 int x = getPlaybackXPos(currentPlaybackFramePosition); 758 //System.out.println("*** playback x = " + x); 759 760 x = (int)Math.rint(((double)x) * getTimeStretchFactor()); // ****** 745 761 746 762 if (x >= 0 && x <= getWidth()) { 747 763 748 764 ((Graphics2D)g).setStroke(GRAPH_BAR_STROKE); 749 765 g.setColor(PLAYBACK_BAR_COLOR); -
trunk/src/org/apollo/gui/WaveFormRenderProccessingUnit.java
r1146 r1561 3 3 import java.awt.Graphics2D; 4 4 import java.util.LinkedList; 5 import java.util.List; 5 6 6 7 import javax.sound.sampled.AudioFormat; … … 269 270 for (int i = 0; i < amps.length; i+=2) { 270 271 272 g.setColor(SwingConversions.toSwingColor(ApolloColorIndexedModels.WAVEFORM_COLOR)); 273 271 274 float peak = amps[i]; 272 275 float trough = amps[i + 1]; … … 293 296 } 294 297 298 int frameSize = 4; 299 int bi_start = (currentTask.startFrame + renderStart); 300 int bi_end = bi_start + (renderLength); 301 302 for (int bi = bi_start; bi<bi_end; bi++) { 303 if (currentTask.frameIsBeat[bi]) { 304 g.setColor(SwingConversions.toSwingColor(ApolloColorIndexedModels.WAVEFORM_SELECTION_COLOR)); 305 g.drawLine(x, halfMaxHeight, x, -halfMaxHeight); 306 break; 307 } 308 } 309 295 310 currentAmplitude ++; 296 311 } … … 303 318 } // next pass 304 319 305 // Less ion learnt: do not request lots of requests to repaint306 // later on the AWT Event queu otherwise it will get congested320 // Lesson learnt: do not request lots of requests to repaint 321 // later on the AWT Event queue otherwise it will get congested 307 322 // and will freeze up the interact for annoying periods of time. 308 323 currentTask.setState(WaveFormRenderTask.STATE_STOPPED); … … 348 363 private Image imageBuffer; // nullified when stopped. 349 364 private byte[] audioBytes; // nullified when stopped. - Arrays (not contents) are immutable so no need to worry about threading issues with indexes 365 private boolean[] frameIsBeat; 366 350 367 private final int startFrame; 351 368 private final int frameLength; // in frames … … 357 374 byte[] audioBytes, 358 375 AudioFormat format, 376 List<Double> detectedBeats, 359 377 int startFrame, 360 378 int frameLength, … … 371 389 this.frameLength = frameLength; 372 390 this.recommendInvalidations = recommendInvalidations; 391 392 this.frameIsBeat = new boolean[frameLength]; 393 if (detectedBeats != null) { 394 for (double beat_in_secs: detectedBeats){ 395 int frame_pos = (int)Math.round(beat_in_secs * format.getSampleRate()); 396 frameIsBeat[frame_pos] = true; 397 } 398 } 399 373 400 renderer = new DualPeakTroughWaveFormRenderer(format); 374 401 } … … 384 411 if (state == STATE_STOPPED) { 385 412 audioBytes = null; 413 frameIsBeat = null; 386 414 imageBuffer = null; 387 415 } -
trunk/src/org/apollo/widgets/LinkedTrack.java
r1142 r1561 1504 1504 { 1505 1505 public PlaybackPopup() { 1506 super(); 1507 1506 1508 miscButton.setActionCommand("goto"); 1507 1509 SwingMiscManager.setJButtonIcon(miscButton, IconRepository.getIcon("goto.png")); … … 1554 1556 } 1555 1557 1558 @Override 1559 protected void beatDetectChanged() { 1560 1561 System.err.println("*** Need to implement beat detection for linked tracks"); 1562 /*boolean toggleDetectBeat = beatDetectButton.isSelected(); 1563 1564 updateData(TrackWidgetCommons.META_BEAT_DETECT_TAG, TrackWidgetCommons.META_BEAT_DETECT_TAG + toggleDetectBeat); 1565 1566 if (toggleDetectBeat) { 1567 runDetectBeats(); 1568 // cause refresh 1569 }*/ 1570 } 1556 1571 } 1557 1572 -
trunk/src/org/apollo/widgets/SampledTrack.java
r1557 r1561 27 27 import javax.sound.sampled.LineUnavailableException; 28 28 import javax.sound.sampled.UnsupportedAudioFileException; 29 import javax.swing.ButtonModel; 29 30 import javax.swing.JSlider; 30 31 import javax.swing.SwingUtilities; … … 72 73 import org.expeditee.gio.swing.SwingConversions; 73 74 import org.expeditee.gio.swing.SwingMiscManager; 75 import org.expeditee.gui.Browser; 74 76 import org.expeditee.gui.DisplayController; 75 77 import org.expeditee.gui.Frame; 76 78 import org.expeditee.gui.FrameIO; 77 79 import org.expeditee.gui.PopupManager; 80 import org.expeditee.gui.PopupManager.ExpandShrinkAnimator; 78 81 import org.expeditee.gui.management.ResourceManager; 79 82 import org.expeditee.items.ItemParentStateChangedEvent; … … 101 104 import be.tarsos.dsp.io.jvm.WaveformWriter; 102 105 106 107 103 108 /** 104 109 * The sampled track widgets in apollo. … … 109 114 public class SampledTrack extends HeavyDutyInteractiveWidget implements TrackModelHandler, EffecientInvalidator, Observer { 110 115 111 /** The observered subject. Can be null */ 116 /** The observed subject. Can be null */ 117 private SampledTrackModel unityTrackModel = null; 112 118 private SampledTrackModel trackModel = null; 113 119 … … 144 150 145 151 146 /** If a track widget has a data string that ycontains META_SHOULD_INDEX_AUDIO_TAG, then147 * the track should not be indexed for searching the audio.... default is does not exist152 /** If a track widget has a data string that contains META_SHOULD_INDEX_AUDIO_TAG, then 153 * the track should not be indexed for searching the audio.... default is that it does not exist 148 154 */ 149 155 public static final String META_DONT_INDEX_AUDIO_TAG = "dontindexaudio"; … … 170 176 true); 171 177 178 if (Browser.DEBUG) { 179 System.out.println("**** SampleTrack(source,audiobytes,format,mixTemplate): source="+ source); 180 } 172 181 // Must set upon construction - always 173 182 localFileName = AudioPathManager.generateLocateFileName("wav"); 174 183 updateData(META_LOCALNAME_TAG, META_LOCALNAME_TAG + localFileName); 175 184 176 trackModel = new SampledTrackModel(audioBytes, format, localFileName); 177 185 unityTrackModel = new SampledTrackModel(audioBytes, format, localFileName); 186 trackModel = unityTrackModel; 187 188 boolean detectBeat = getStrippedDataBool(TrackWidgetCommons.META_BEAT_DETECT_TAG,false); 189 if (detectBeat) { 190 runDetectBeats(); 191 } 192 178 193 // Ensure that the model is marked as modified so that it will save 179 194 trackModel.setAudioModifiedFlag(true); 180 195 181 196 trackModel.setName(getStrippedDataString(TrackWidgetCommons.META_NAME_TAG)); 182 197 198 183 199 // Create the immutable mix subject 184 200 if (mixTemplate == null) { … … 222 238 TrackWidgetCommons.CACHE_DEPTH); 223 239 240 if (Browser.DEBUG) { 241 System.out.println("**** SampleTrack(source,args): source=" + source); 242 } 243 224 244 // Read the metadata 225 245 localFileName = getStrippedDataString(META_LOCALNAME_TAG); … … 261 281 } 262 282 } 283 284 private void runDetectBeats() 285 { 286 if (Browser.DEBUG) { 287 System.out.println("*** runDetectBeats()"); 288 } 289 try { 290 // consider adding support for parameters from data statement 291 int size = 512; 292 int overlap = 256; 293 trackModel.detectBeats(size,overlap); 294 } 295 catch (Exception ex) { 296 ex.printStackTrace(); 297 } 298 } 299 263 300 264 301 private void createGUI() { … … 281 318 282 319 shouldOmitAudioIndexing = containsDataTrimmedIgnoreCase(META_DONT_INDEX_AUDIO_TAG); 283 320 321 boolean beatDetect=getStrippedDataBool(TrackWidgetCommons.META_BEAT_DETECT_TAG,false); 322 284 323 playbackControlPopup = new PlaybackPopup(); 324 playbackControlPopup.beatDetectButton.setSelected(beatDetect); 285 325 286 326 fulltrackView = (EditableSampledTrackGraphView)_swingComponent; … … 317 357 if (playbackControlPopup == null) { 318 358 playbackControlPopup = new PlaybackPopup(); 359 319 360 } 320 361 … … 329 370 330 371 // Determine where popup should show 331 //int x = SampledTrack.this.getX();372 int x = SampledTrack.this.getX(); 332 373 int y = SampledTrack.this.getY() - playbackControlPopup.getFullBounds().getHeight() - 2; // by default show above 333 374 … … 340 381 animationSource.y = y - 2; 341 382 } 342 383 animationSource.x = x; 384 343 385 // Animate the popup 344 386 playbackControlPopup.getAutoHideTime().setLifetime(TrackWidgetCommons.POPUP_LIFETIME); 345 387 PopupManager.getInstance().add(playbackControlPopup); 388 346 389 playbackControlPopup.show(); 347 390 } else { … … 459 502 } 460 503 504 else if (e.isControlDown() && e.getKeyCode() == KeyEvent.VK_S) { 505 // Stop 506 TrackSequence ts = SoundDesk.getInstance().getTrackSequence(trackMix.getChannelID()); 507 508 // reset any paused mark 509 SoundDesk.getInstance().setPaused(trackMix.getChannelID(), false); 510 511 if (ts != null && 512 ts.isPlaying()) { 513 // Stop playback 514 ApolloPlaybackMixer.getInstance().stop(ts); 515 } 516 517 } else if (e.isControlDown() && e.getKeyCode() == KeyEvent.VK_R) { 518 // rewind 519 520 trackModel.setSelection(0, 0); 521 SoundDesk.getInstance().setPaused(trackMix.getChannelID(), false); 522 } 523 else if (e.isControlDown() && e.getKeyCode() == KeyEvent.VK_B) { 524 525 boolean detectBeat = getStrippedDataBool(TrackWidgetCommons.META_BEAT_DETECT_TAG,false); 526 boolean toggleDetectBeat = (detectBeat) ? false : true; 527 528 updateData(TrackWidgetCommons.META_BEAT_DETECT_TAG, TrackWidgetCommons.META_BEAT_DETECT_TAG + toggleDetectBeat); 529 530 if (toggleDetectBeat) { 531 runDetectBeats(); 532 } 533 } 461 534 // Toggle pitch-track indexing 462 535 else if (e.isControlDown() && e.getKeyCode() == KeyEvent.VK_I) { … … 753 826 data.add(TrackWidgetCommons.META_RUNNINGMSTIME_TAG + getRunningMSTimeFromRawAudio()); 754 827 828 boolean beatDetect=getStrippedDataBool(TrackWidgetCommons.META_BEAT_DETECT_TAG,false); 829 if (beatDetect) { 830 data.add(TrackWidgetCommons.META_BEAT_DETECT_TAG + "true"); 831 } 832 755 833 return data; 756 834 } … … 844 922 try { 845 923 846 trackModel = TrackModelLoadManager.getInstance().load(f.getPath(), localFileName, this, false); 924 unityTrackModel = TrackModelLoadManager.getInstance().load(f.getPath(), localFileName, this, false); 925 trackModel = unityTrackModel; 847 926 848 927 if (trackModel == null) { // load operation canceled … … 850 929 return LOAD_STATE_INCOMPLETED; 851 930 852 } else if (isImporting) { // ensure that file path is null - since not yet saved931 } else if (isImporting) { // ensure that file path is null - since not yet saved 853 932 trackModel.setFilepath(null); 854 933 … … 889 968 } 890 969 970 boolean beatDetect = getStrippedDataBool(TrackWidgetCommons.META_BEAT_DETECT_TAG, false); 971 if (beatDetect) { 972 runDetectBeats(); 973 } 974 891 975 initObservers(); // sets default name if non set 892 976 … … 913 997 if (tinf == null) { 914 998 915 // Determine new init ation time according to position999 // Determine new initiation time according to position 916 1000 long initTime = (parent != null) ? 917 1001 FrameLayoutDaemon.getInstance().getMSAtX(getX(), parent) 918 1002 : 0; 919 1003 920 // Keep TrackGraphModel consist ant1004 // Keep TrackGraphModel consistent 921 1005 AudioStructureModel.getInstance().onTrackWidgetAnchored( 922 1006 localFileName, … … 938 1022 939 1023 // Notify layout manager - not really needed but to be extra safe force the daemon 940 // to be super consist ant1024 // to be super consistent 941 1025 FrameLayoutDaemon.getInstance().forceRecheck(); 942 1026 … … 1144 1228 /** 1145 1229 * To be called by the swing thread only 1146 * This is ne ssessary to avoid runtime memory leaks!!1230 * This is necessary to avoid runtime memory leaks!! 1147 1231 */ 1148 1232 private void releaseMemory(boolean onlyIfExpired) { … … 1321 1405 parent = getParentFrame(); 1322 1406 1323 // Keep TrackGraphModel consist ant1407 // Keep TrackGraphModel consistent 1324 1408 AudioStructureModel.getInstance().onTrackWidgetAudioEdited( 1325 1409 localFileName, … … 1749 1833 * @return 1750 1834 * The initiation time or this track in MS. 1751 * null if unav ilable.1835 * null if unavailable. 1752 1836 */ 1753 1837 public Mutable.Long getInitiationTimeFromMeta() { … … 2026 2110 public PlaybackPopup() 2027 2111 { 2112 super(); 2113 2028 2114 miscButton.setActionCommand("expand"); 2029 2115 SwingMiscManager.setJButtonIcon(miscButton, IconRepository.getIcon("expand.png")); … … 2044 2130 public void onShow() 2045 2131 { 2132 // Make sure the popup is in the most up to date position, 2133 // relative to the SampledTrack 2134 ExpandShrinkAnimator es_animator = (ExpandShrinkAnimator)this.getAnimator(); 2135 2136 int pcp_x_dim = this.getFullBounds().getWidth(); 2137 int pcp_y_dim = this.getFullBounds().getHeight(); 2138 2139 int pcp_x_org = SampledTrack.this.getX(); 2140 int pcp_y_org = SampledTrack.this.getY() - pcp_y_dim - 2; // by default show above 2141 2142 if (pcp_y_org < 0) { 2143 // if doesn't fit above, show below 2144 pcp_y_org = SampledTrack.this.getY() + SampledTrack.this.getHeight() + 2; 2145 } 2146 2147 AxisAlignedBoxBounds initial_bounds = new AxisAlignedBoxBounds(pcp_x_org,pcp_y_org,pcp_x_dim,pcp_y_dim); 2148 2149 es_animator.setInitialBounds(initial_bounds); 2150 2046 2151 // Listen for volume or mute changed events 2047 2152 trackMix.addObserver(this); … … 2088 2193 SoundDesk.getInstance().setPaused(trackMix.getChannelID(), false); 2089 2194 2090 } else if (e.getSource() == miscButton) { 2195 } 2196 else if (e.getSource() == beatDetectButton) { 2197 2198 boolean detectBeat = getStrippedDataBool(TrackWidgetCommons.META_BEAT_DETECT_TAG,false); 2199 boolean toggleDetectBeat = (detectBeat) ? false : true; 2200 2201 updateData(TrackWidgetCommons.META_BEAT_DETECT_TAG, TrackWidgetCommons.META_BEAT_DETECT_TAG + toggleDetectBeat); 2202 2203 if (toggleDetectBeat) { 2204 runDetectBeats(); 2205 } 2206 } 2207 else if (e.getSource() == miscButton) { 2091 2208 expand(false); 2092 2209 } … … 2286 2403 if (stretched_track_model != null) { 2287 2404 trackModel = stretched_track_model; 2405 fulltrackView.setTimeStretchFactor(time_stretch); 2288 2406 } 2289 2407 } 2408 else { 2409 double prev_time_stretch_factor = fulltrackView.getTimeStretchFactor(); 2410 if (prev_time_stretch_factor != 1.0) { 2411 trackModel = unityTrackModel; 2412 fulltrackView.setTimeStretchFactor(1.0); 2413 } 2414 } 2415 } 2416 else { 2417 trackModel = unityTrackModel; 2418 fulltrackView.setTimeStretchFactor(1.0); 2290 2419 } 2291 2420 … … 2432 2561 ); 2433 2562 } 2563 2564 2565 @Override 2566 protected void beatDetectChanged() { 2567 2568 ButtonModel buttonModel = beatDetectButton.getModel(); 2569 boolean isSelected = buttonModel.isSelected(); 2570 boolean isPressed = buttonModel.isPressed(); 2571 2572 if (Browser.DEBUG) { 2573 System.out.println("**** isPressed=" + isPressed + ", isSelected=" + isSelected); 2574 } 2575 2576 if (isPressed) { 2577 2578 boolean newBeatDetectState = isSelected; 2579 boolean curBeatDetectState = getStrippedDataBool(TrackWidgetCommons.META_BEAT_DETECT_TAG,false); 2580 2581 if (Browser.DEBUG) { 2582 System.out.println("**** curBeatDetectState=" + curBeatDetectState + ", newBeatDetectState=" + newBeatDetectState); 2583 } 2584 2585 if (newBeatDetectState != curBeatDetectState) { 2586 2587 // change of state has occurred 2588 updateData(TrackWidgetCommons.META_BEAT_DETECT_TAG, TrackWidgetCommons.META_BEAT_DETECT_TAG + newBeatDetectState); 2589 2590 if (newBeatDetectState==true) { 2591 runDetectBeats(); 2592 } 2593 else { 2594 trackModel.clearBeats(); 2595 } 2596 2597 EditableSampledTrackGraphView thisTrackView = (EditableSampledTrackGraphView)_swingComponent; 2598 thisTrackView.releaseBuffer(); 2599 thisTrackView.updateBuffer(); 2600 } 2601 } 2602 } 2434 2603 } 2435 2604 -
trunk/src/org/apollo/widgets/TrackWidgetCommons.java
r1102 r1561 17 17 public static final String META_LAST_WIDTH_TAG = "lw="; 18 18 public static final String META_OMIT_LAYOUT_TAG = "dontlayout"; 19 public static final String META_BEAT_DETECT_TAG="beatDetect="; 20 19 21 20 22 public static final int CACHE_DEPTH = 1;
Note:
See TracChangeset
for help on using the changeset viewer.