annotate 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
rev   line source
f@0 1 /*
f@0 2 Cross-Modal DAW Prototype - Prototype of a simple Cross-Modal Digital Audio Workstation.
f@0 3
f@0 4 Copyright (C) 2015 Queen Mary University of London (http://depic.eecs.qmul.ac.uk/)
f@0 5
f@0 6 This program is free software: you can redistribute it and/or modify
f@0 7 it under the terms of the GNU General Public License as published by
f@0 8 the Free Software Foundation, either version 3 of the License, or
f@0 9 (at your option) any later version.
f@0 10
f@0 11 This program is distributed in the hope that it will be useful,
f@0 12 but WITHOUT ANY WARRANTY; without even the implied warranty of
f@0 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f@0 14 GNU General Public License for more details.
f@0 15
f@0 16 You should have received a copy of the GNU General Public License
f@0 17 along with this program. If not, see <http://www.gnu.org/licenses/>.
f@0 18 */
f@0 19 package uk.ac.qmul.eecs.depic.daw;
f@0 20
f@0 21 import uk.ac.qmul.eecs.depic.patterns.Range;
f@0 22
f@1 23 /**
f@1 24 *
f@1 25 * A Clip is a piece of audio Sample. Clips representing different parts of the same audio sample all share
f@1 26 * a reference to the same Sample. This way manipulating clips doesn't involve manipulating all the samples but
f@1 27 * just references to them.
f@1 28 *
f@1 29 */
f@0 30 public class Clip extends Range<Integer> implements Comparable<Clip> {
f@0 31 private Sample sample;
f@0 32 private int sampleStart;
f@0 33 private float startMs;
f@0 34 private float endMs;
f@0 35 private float millisecPerChunk;
f@0 36 private float sampleStartMs;
f@0 37
f@0 38 public Clip(int start, int end, Sample sample, int sampleStart, float millisecPerChunk) {
f@0 39 super(start, end);
f@0 40 this.sample = sample;
f@0 41 this.sampleStart = sampleStart;
f@0 42
f@0 43 this.millisecPerChunk = millisecPerChunk;
f@0 44 updateTimeMs();
f@0 45 sampleStartMs = sampleStart * millisecPerChunk;
f@0 46 }
f@0 47
f@0 48 /**
f@0 49 *
f@0 50 * Copy constructor
f@0 51 *
f@0 52 * @param c another instance of {@code Clip}
f@0 53 */
f@0 54 public Clip(Clip c){
f@0 55 this(c.start,c.end,c.sample,c.sampleStart,c.millisecPerChunk);
f@0 56 }
f@0 57
f@0 58 private void updateTimeMs(){
f@0 59 startMs = start * millisecPerChunk;
f@0 60 endMs = end * (millisecPerChunk) + millisecPerChunk;
f@0 61 }
f@0 62
f@0 63 /**
f@0 64 * Shifts the clips of the amount given as argument
f@0 65 * @param amount
f@0 66 */
f@0 67 public void shift(int amount){
f@0 68 start += amount;
f@0 69 end = end += amount;
f@0 70
f@0 71 updateTimeMs();
f@0 72 }
f@0 73
f@0 74 public void setStartAt(int position){
f@0 75 int diff = position - start;
f@0 76 start = position;
f@0 77 end = end + diff;
f@0 78
f@0 79 updateTimeMs();
f@0 80 }
f@0 81
f@0 82 public Sample getSample() {
f@0 83 return sample;
f@0 84 }
f@0 85
f@0 86 /**
f@0 87 * Returns the chunks index where this selection starts relative to the start of the sample.
f@0 88 *
f@0 89 * This is different from {@code getStart()}, as {@code getStart()} returns the
f@0 90 * absolute position (a.k.a. chunk index) of the selection start
f@0 91 *
f@0 92 * @return
f@0 93 */
f@0 94 public int getSampleStart(){
f@0 95 return sampleStart;
f@0 96 }
f@0 97
f@0 98 public float getSampleStartMs(){
f@0 99 return sampleStartMs;
f@0 100 }
f@0 101
f@0 102 public float getStartTimeMs(){
f@0 103 return startMs;
f@0 104 }
f@0 105
f@0 106 public float getEndTimeMs(){
f@0 107 return endMs;
f@0 108 }
f@0 109
f@0 110 public float getMillisecPerChunk(){
f@0 111 return millisecPerChunk;
f@0 112 }
f@0 113
f@0 114 /**
f@0 115 * Checks whether {@code p} is contained in the selection,
f@0 116 * that is greater than {@code getStart()} and lower than {@code getEnd()}.
f@0 117 *
f@0 118 *
f@0 119 * @param p the integer value to check for
f@0 120 * @return {@code true} if {@code pos} is contained in the selection, {@code false} otherwise
f@0 121 */
f@0 122 public boolean contains(int pos){
f@0 123 return ((pos>=getStart()) && (pos<=getEnd()));
f@0 124 }
f@0 125
f@0 126 public boolean containsTime(float time){
f@0 127 return time >= startMs && time <= endMs;
f@0 128 }
f@0 129
f@0 130 /**
f@0 131 * Splits the selection around the given position.
f@0 132 *
f@0 133 * If {@code pos} is less than the clip start or greater than the clip end, then the array will have size 1 and will
f@0 134 * 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
f@0 135 * from {@code geStart()} to {@code pos-1}, whereas the clip at index 1 will range from {@code pos} to {@code getEnd()}
f@0 136 *
f@0 137 *
f@0 138 * @param pos the split position
f@0 139 * @return an array of one or two clips, resulted from a split at position {@code pos}
f@0 140 */
f@0 141 public Clip [] split(int pos){
f@0 142 /* if pos can go from start+1 to end *
f@0 143 * if pos == start+1, the split will be [start,start] and [start+1,end] *
f@0 144 * if pos == end, the split will be [start,end-1] and [end,end] */
f@0 145 if(pos <= getStart() || pos > getEnd()){
f@0 146 return new Clip [] {this};
f@0 147 }else{
f@0 148 return new Clip [] {
f@0 149 new Clip(getStart(),pos-1,sample,sampleStart,millisecPerChunk),
f@0 150 new Clip(pos,getEnd(),sample,sampleStart+pos-getStart(),millisecPerChunk)
f@0 151 };
f@0 152 }
f@0 153 }
f@0 154
f@0 155 @Override
f@0 156 public int compareTo(Clip s) {
f@0 157 return getStart().compareTo(s.getStart());
f@0 158 }
f@0 159
f@0 160 @Override
f@0 161 public String toString(){
f@0 162 return super.toString()+ ", selection in Ms:["+startMs+","+endMs+"], sample:"+ sample+ ", sample start:" +sampleStart;
f@0 163 }
f@0 164
f@0 165 public static Clip join(Clip clip1, Clip clip2){
f@0 166 /* nulls not joinable */
f@0 167 if(clip1 == null || clip2 == null){
f@0 168 return null;
f@0 169 }
f@0 170
f@0 171 /* clips with different sample or different resolution not joinable */
f@0 172 if(!clip1.sample.equals(clip2.sample) || clip1.millisecPerChunk != clip2.millisecPerChunk ){
f@0 173 return null;
f@0 174 }
f@0 175
f@0 176 /* try clip2 after clip1 */
f@0 177 if(clip1.end+1 == clip2.start){
f@0 178 int clip1Len = clip1.end - clip1.start;
f@0 179
f@0 180 if(clip1.sampleStart + clip1Len + 1 == clip2.sampleStart){
f@0 181 return new Clip(
f@0 182 clip1.start,
f@0 183 clip2.end,
f@0 184 clip1.sample,
f@0 185 clip1.sampleStart,
f@0 186 clip1.millisecPerChunk
f@0 187 );
f@0 188 }
f@0 189 /* try clip1 after clip2 */
f@0 190 }else if(clip2.end+1 == clip1.start){
f@0 191 int clip2Len = clip2.end - clip2.start;
f@0 192
f@0 193 if(clip2.sampleStart + clip2Len + 1 == clip2.sampleStart){
f@0 194 return new Clip(
f@0 195 clip2.start,
f@0 196 clip1.end,
f@0 197 clip2.sample,
f@0 198 clip2.sampleStart,
f@0 199 clip2.millisecPerChunk
f@0 200 );
f@0 201 }
f@0 202 }
f@0 203
f@0 204 /* not joinable */
f@0 205 return null;
f@0 206 }
f@0 207
f@0 208 }