Mercurial > hg > cmdp
view src/uk/ac/qmul/eecs/depic/daw/Clip.java @ 4:473da40f3d39 tip
added html formatting to Daw/package-info.java
author | Fiore Martin <f.martin@qmul.ac.uk> |
---|---|
date | Thu, 25 Feb 2016 17:50:09 +0000 |
parents | 629262395647 |
children |
line wrap: on
line source
/* Cross-Modal DAW Prototype - Prototype of a simple Cross-Modal Digital Audio Workstation. Copyright (C) 2015 Queen Mary University of London (http://depic.eecs.qmul.ac.uk/) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package uk.ac.qmul.eecs.depic.daw; import uk.ac.qmul.eecs.depic.patterns.Range; /** * * A Clip is a piece of audio Sample. Clips representing different parts of the same audio sample all share * a reference to the same Sample. This way manipulating clips doesn't involve manipulating all the samples but * just references to them. * */ public class Clip extends Range<Integer> implements Comparable<Clip> { private Sample sample; private int sampleStart; private float startMs; private float endMs; private float millisecPerChunk; private float sampleStartMs; public Clip(int start, int end, Sample sample, int sampleStart, float millisecPerChunk) { super(start, end); this.sample = sample; this.sampleStart = sampleStart; this.millisecPerChunk = millisecPerChunk; updateTimeMs(); sampleStartMs = sampleStart * millisecPerChunk; } /** * * Copy constructor * * @param c another instance of {@code Clip} */ public Clip(Clip c){ this(c.start,c.end,c.sample,c.sampleStart,c.millisecPerChunk); } private void updateTimeMs(){ startMs = start * millisecPerChunk; endMs = end * (millisecPerChunk) + millisecPerChunk; } /** * Shifts the clips of the amount given as argument * @param amount */ public void shift(int amount){ start += amount; end = end += amount; updateTimeMs(); } public void setStartAt(int position){ int diff = position - start; start = position; end = end + diff; updateTimeMs(); } public Sample getSample() { return sample; } /** * Returns the chunks index where this selection starts relative to the start of the sample. * * This is different from {@code getStart()}, as {@code getStart()} returns the * absolute position (a.k.a. chunk index) of the selection start * * @return */ public int getSampleStart(){ return sampleStart; } public float getSampleStartMs(){ return sampleStartMs; } public float getStartTimeMs(){ return startMs; } public float getEndTimeMs(){ return endMs; } public float getMillisecPerChunk(){ return millisecPerChunk; } /** * Checks whether {@code p} is contained in the selection, * that is greater than {@code getStart()} and lower than {@code getEnd()}. * * * @param p the integer value to check for * @return {@code true} if {@code pos} is contained in the selection, {@code false} otherwise */ public boolean contains(int pos){ return ((pos>=getStart()) && (pos<=getEnd())); } public boolean containsTime(float time){ return time >= startMs && time <= endMs; } /** * Splits the selection around the given position. * * If {@code pos} is less than the clip start or greater than the clip end, then the array will have size 1 and will * contain this Clip. Conversely if {@code pos} is contained in this clip an array with two new instances of {@code Clip} is returned. The clip at index 0, will range * from {@code geStart()} to {@code pos-1}, whereas the clip at index 1 will range from {@code pos} to {@code getEnd()} * * * @param pos the split position * @return an array of one or two clips, resulted from a split at position {@code pos} */ public Clip [] split(int pos){ /* if pos can go from start+1 to end * * if pos == start+1, the split will be [start,start] and [start+1,end] * * if pos == end, the split will be [start,end-1] and [end,end] */ if(pos <= getStart() || pos > getEnd()){ return new Clip [] {this}; }else{ return new Clip [] { new Clip(getStart(),pos-1,sample,sampleStart,millisecPerChunk), new Clip(pos,getEnd(),sample,sampleStart+pos-getStart(),millisecPerChunk) }; } } @Override public int compareTo(Clip s) { return getStart().compareTo(s.getStart()); } @Override public String toString(){ return super.toString()+ ", selection in Ms:["+startMs+","+endMs+"], sample:"+ sample+ ", sample start:" +sampleStart; } public static Clip join(Clip clip1, Clip clip2){ /* nulls not joinable */ if(clip1 == null || clip2 == null){ return null; } /* clips with different sample or different resolution not joinable */ if(!clip1.sample.equals(clip2.sample) || clip1.millisecPerChunk != clip2.millisecPerChunk ){ return null; } /* try clip2 after clip1 */ if(clip1.end+1 == clip2.start){ int clip1Len = clip1.end - clip1.start; if(clip1.sampleStart + clip1Len + 1 == clip2.sampleStart){ return new Clip( clip1.start, clip2.end, clip1.sample, clip1.sampleStart, clip1.millisecPerChunk ); } /* try clip1 after clip2 */ }else if(clip2.end+1 == clip1.start){ int clip2Len = clip2.end - clip2.start; if(clip2.sampleStart + clip2Len + 1 == clip2.sampleStart){ return new Clip( clip2.start, clip1.end, clip2.sample, clip2.sampleStart, clip2.millisecPerChunk ); } } /* not joinable */ return null; } }