Skip to content

Commit

Permalink
copied source from Gravity Beats
Browse files Browse the repository at this point in the history
  • Loading branch information
Jaxan committed Mar 25, 2013
1 parent 018cb17 commit 61c889b
Show file tree
Hide file tree
Showing 5 changed files with 491 additions and 0 deletions.
86 changes: 86 additions & 0 deletions Beat.h
@@ -0,0 +1,86 @@
//
// Beat.h
// GravityBeats
//
// Created by Joshua Moerman on 1/9/13.
// Copyright (c) 2013 Vadovas. All rights reserved.
//

#ifndef GravityBeats_Beat_h
#define GravityBeats_Beat_h

#include <vector>
#include <cmath>

#include "UserInformation.h"

template <typename Information>
struct Note : public UserInformation<Information>{
// see http://en.wikipedia.org/wiki/Note_value
enum Speed {
kWholeNote =1, // 1 in one measure
kHalfNote =2, // 2 in one measure
kTriplet =3, // 3 in one measure
kQuarterNote =4, // 4
kHalfTriplet =6, // 6
kEighthNote =8 // 8
} speed;
int progress = -2;

template <typename... S>
Note(Speed speed, S... args)
: UserInformation<Information>(args...)
, speed(speed)
{}

// we could return how much it is off, to give the balls the right initial position and speed.
bool update(float time_in_measure){
int new_progress = std::floor(time_in_measure*speed);
if(new_progress != progress){
if(progress == -2){
progress = new_progress;
return false;
} else {
progress = new_progress;
return true;
}
}
return false;
}

void reset(){
progress = -1;
}
};

template <typename NoteInformation>
struct Beat {
float total_length{4.0}; // 60 bpm
float time{-0.1};

std::vector<Note<NoteInformation>> notes;

std::vector<NoteInformation> update(float dt){
std::vector<NoteInformation> ret;
time += dt;

// not needed, but keeps the floats small
// also usefull when we want to change bpm
if(time > total_length){
time -= total_length;
for(auto& n : notes){
n.reset();
}
}

for(auto& n : notes){
if(n.update(time / total_length)){
ret.push_back(n.information);
}
}

return ret;
}
};

#endif
99 changes: 99 additions & 0 deletions Math.h
@@ -0,0 +1,99 @@
//
// Math.h
// GravityBeats
//
// Created by Joshua Moerman on 1/12/13.
// Copyright (c) 2013 Vadovas. All rights reserved.
//

#ifndef GravityBeats_Math_h
#define GravityBeats_Math_h

#include <cmath>

namespace math {
struct Vec2 {
float x, y;

Vec2& operator *= (float rh){
x *= rh;
y *= rh;
return *this;
}

Vec2& operator+= (Vec2 const & rh){
x += rh.x;
y += rh.y;
return *this;
}

float sqr_length() const {
return x*x + y*y;
}

float length() const {
return std::sqrt(sqr_length());
}

Vec2& normalize(){
const float l = length();
if(l == 0.0f) { return *this; }
x /= l;
y /= l;
return *this;
}
};

inline Vec2 operator*(float lh, Vec2 rh){
rh *= lh;
return rh;
}

inline Vec2 operator+(Vec2 lh, Vec2 const & rh){
return lh += rh;
}

inline Vec2 operator-(Vec2 lh, Vec2 const & rh){
return lh += -1.0*rh;
}

inline float dot(Vec2 const & lh, Vec2 const & rh){
return lh.x*rh.x + lh.y*rh.y;
}

inline Vec2 rotate_ccw(Vec2 v){
std::swap(v.x, v.y);
v.x *= -1.0;
return v;
}

inline Vec2 normalize(Vec2 v){
return v.normalize();
}

inline float distance_point_point(Vec2 p1, Vec2 p2){
return (p2 - p1).length();
}

// p point, [v,w] line segment
inline float distance_point_line(Vec2 p, Vec2 v, Vec2 w){
// http://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment
const float l2 = (v-w).sqr_length();
if (l2 == 0.0) return distance_point_point(p, v);

const float t = dot(p - v, w - v) / l2;
if (t < 0.0) return distance_point_point(p, v);
else if (t > 1.0) return distance_point_point(p, w);

auto projection = v + t * (w - v);
return distance_point_point(p, projection);
}

template <typename T>
constexpr T clamp(T input, T min, T max){
return input > max ? max :
input < min ? min : input;
}
}

#endif
70 changes: 70 additions & 0 deletions Scales.h
@@ -0,0 +1,70 @@
//
// Scales.h
// GravityBeats
//
// Created by Joshua Moerman on 1/25/13.
// Copyright (c) 2013 Vadovas. All rights reserved.
//

#ifndef GravityBeats_Scales_h
#define GravityBeats_Scales_h

#include <vector>
#include <cmath>
#include <iostream>
#include <fstream>
#include <stdexcept>

// http://www.phys.unsw.edu.au/jw/notes.html

inline float pitch_for_midi_note(int note){
// we say 440hz is 1 in our units
float exponent = (note - 69) / 12.0f;
return std::pow(2.0f, exponent);
}

struct Scale {
std::vector<int> notes;

int note_for_length(float length){
// determine note
length /= 200.0;
float note = -std::log(length) / std::log(2.0f) * 12.0f + 69.0f;

// determine note in scale
auto it = notes.begin();
while(*it < note && it != notes.end()){
++it;
}

// determine closest note in scale
if(it == notes.begin()){
return *it;
} else {
auto it2 = it - 1;
if(std::abs(*it - note) > std::abs(*it2 - note)){
return *it2;
} else {
return *it;
}
}
}

static Scale load_from_file(std::string filename){
std::ifstream file(filename);
if(!file) throw std::runtime_error("Couldn't open file " + filename);

Scale scale;

int note = 0;
while (file >> note) {
scale.notes.push_back(note);
}

std::sort(scale.notes.begin(), scale.notes.end());

return scale;
}
};

#endif

0 comments on commit 61c889b

Please sign in to comment.