package edu.msoe.taylor.audio; /** * The Note class describes a note. Each note must have duration and either a * pitch specified in scientific pitch notation or a frequency. If scientific * pitch is specified, the frequency is calculated. * * @see Scientific Pitch Notation * * @author t a y l o r@msoe.edu * @version 2014.04.11 */ public class Note { /** * Name of note in scientific pitch notation. */ private final String name; /** * Frequency of note in cycles per second. */ private final float frequency; /** * Duration of note in milliseconds. */ private final float duration; /** * Frequency for A0 */ private static final float A0 = 27.5f; /** * Constructs a new Note object with the specified pitch and duration. * @param name Scientific pitch notation for the note * @param duration Duration of the note in milliseconds */ public Note(String name, float duration) { this.name = name; frequency = getFrequency(name); if(duration<0) { throw new IllegalArgumentException("Invalid duration (cannot be negative)."); } this.duration = duration; } /** * Constructs a new Note object with the specified frequency and duration. * @param frequency Frequency in hertz * @param duration Duration in milliseconds */ public Note(float frequency, float duration) { this.name = null; if(frequency<0) { throw new IllegalArgumentException("Invalid frequency (cannot be negative)."); } this.frequency = frequency; if(duration<0) { throw new IllegalArgumentException("Invalid duration (cannot be negative)."); } this.duration = duration; } /** * Returns the frequency of the specified scientific pitch * For example: ("C4") specifies middle C on a standard piano (~262Hz) * @param scientificPitch Note from A-G, including sharps (#) with octave * specified as "A4", "A#4", "B4", ... * @return The frequency of the specified note. * @see wikipedia Note entry */ private float getFrequency(String scientificPitch) { String note = ""; int octave; if(scientificPitch.charAt(1)=='#') { note = scientificPitch.substring(0,2); octave = Integer.parseInt(scientificPitch.substring(2)); } else { note = scientificPitch.substring(0,1); octave = Integer.parseInt(scientificPitch.substring(1)); } double power = 0; note = note.toUpperCase(); if(note.equals("C")) { power = (12.0*octave-9)/12; } else if(note.equals("C#")) { power = (12.0*octave-8)/12; } else if(note.equals("D")) { power = (12.0*octave-7)/12; } else if(note.equals("D#")) { power = (12.0*octave-6)/12; } else if(note.equals("E")) { power = (12.0*octave-5)/12; } else if(note.equals("F")) { power = (12.0*octave-4)/12; } else if(note.equals("F#")) { power = (12.0*octave-3)/12; } else if(note.equals("G")) { power = (12.0*octave-2)/12; } else if(note.equals("G#")) { power = (12.0*octave-1)/12; } else if(note.equals("A")) { power = octave; } else if(note.equals("A#")) { power = (12.0*octave+1)/12; } else if(note.equals("B")) { power = (12.0*octave+2)/12; } else { throw new IllegalArgumentException("Note note in scientific pitch notation: " + note); } return A0*(float)Math.pow(2,power); } /** * Returns the frequency (in Hz) of this note. * @return frequency in hertz */ public float getFrequency() { return frequency; } /** * Returns the duration of this note. * @return duration in milliseconds */ public float getDuration() { return duration; } /** * Returns a string representation of the note. */ public String toString() { return "" + (name==null ? frequency : name) + duration; } }