001/**
002 * Copyright (c) 2011, The University of Southampton and the individual contributors.
003 * All rights reserved.
004 *
005 * Redistribution and use in source and binary forms, with or without modification,
006 * are permitted provided that the following conditions are met:
007 *
008 *   *  Redistributions of source code must retain the above copyright notice,
009 *      this list of conditions and the following disclaimer.
010 *
011 *   *  Redistributions in binary form must reproduce the above copyright notice,
012 *      this list of conditions and the following disclaimer in the documentation
013 *      and/or other materials provided with the distribution.
014 *
015 *   *  Neither the name of the University of Southampton nor the names of its
016 *      contributors may be used to endorse or promote products derived from this
017 *      software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030/**
031 * 
032 */
033package org.openimaj.audio.timecode;
034
035import org.openimaj.audio.util.MusicUtils;
036
037/**
038 *      A standard MIDI-timecode that uses measures, beats and ticks. A beat is
039 *      determined by the BPM of the track, while ticks is a given subdivision
040 *      of a beat. Measures is based on the meter of the track.
041 *
042 *      @author David Dupplaw (dpd@ecs.soton.ac.uk)
043 *      
044 *      @created 28 Nov 2011
045 */
046public class MeasuresBeatsTicksTimecode extends AudioTimecode
047{
048        /** Most western music is in four-time */
049        public int beatsPerMeasure = 4;
050        
051        /** Standard MIDI is generally 120 ticks per beat */
052        public int ticksPerBeat = 120;
053        
054        /** Number of beats per minute */
055        public float bpm = 140;
056
057        /** At the given bpm, the number of milliseconds per beat */
058        private int mpb = MusicUtils.millisPerBeat( bpm );
059        
060        /**
061         *      Sets up a 4-time, 120 tick MBT timecode.
062         *      @param bpm
063         */
064        public MeasuresBeatsTicksTimecode( float bpm )
065        {
066                super( 0 );
067                this.bpm = bpm;
068                this.mpb = MusicUtils.millisPerBeat( bpm );
069        }
070        
071        /**
072         *      Create a specific timecode.
073         * 
074         *      @param bpm The number of beats per minute
075         *      @param measures The number of measures
076         *      @param beats The number of beats
077         *      @param ticks The number of ticks
078         */
079        public MeasuresBeatsTicksTimecode( float bpm, long measures, int beats, 
080                        int ticks )
081        {
082                this( bpm );
083                int mpt = mpb / ticksPerBeat;
084                super.milliseconds = mpb * ((measures*beatsPerMeasure)+beats) + 
085                        (mpt*ticks);
086        }
087
088        /**
089         *      Create a specific timecode in a different time signature.
090         * 
091         *      @param bpm The number of beats per minute
092         *      @param measures The number of measures
093         *      @param beats The number of beats
094         *      @param ticks The number of ticks
095         *      @param beatsPerMeasure The number of beats in a measure
096         */
097        public MeasuresBeatsTicksTimecode( float bpm, long measures, int beats, 
098                        int ticks, int beatsPerMeasure )
099        {
100                this( bpm );
101                this.beatsPerMeasure = beatsPerMeasure;
102                int mpt = mpb / ticksPerBeat;
103                super.milliseconds = mpb * ((measures*beatsPerMeasure)+beats) + 
104                        (mpt*ticks);
105        }
106
107        /**
108         *      Returns the number of measures.
109         *      @return The number of measures.
110         */
111        public long getMeasures()
112        {
113                return (milliseconds / mpb) / beatsPerMeasure;
114        }
115        
116        /**
117         *      Returns the number of beats.
118         *      @return The number of beats.
119         */
120        public int getBeats()
121        {
122                return (int)(milliseconds / mpb) % beatsPerMeasure;
123        }
124        
125        /**
126         *      Returns the number of ticks in the current beat. 
127         *      @return The number of ticks in the current beat.
128         */
129        public int getTicks()
130        {
131                float mpt = mpb / (float)ticksPerBeat;
132                return (int)(milliseconds / mpt) % ticksPerBeat;
133        }
134        
135        /**
136         *      {@inheritDoc}
137         *      @see org.openimaj.audio.timecode.AudioTimecode#toString()
138         */
139        @Override
140        public String toString()
141        {
142                return getMeasures()+":"+getBeats()+":"+getTicks();
143        }
144}