CS 312 - Week 5.2 Class
CS 312 Audio Programming Winter 2020
Table of Contents
- 5.2 Class
- Quiz 1 w2020 review
- Test rules
- Terminal commands
- C++
- What is the difference between
- What is a.out?
- What is the size in bytes of the following C++ types on mac
- Write an example of each of these comment types
- operators
- Terms
- Interface and implementation files
- Printing char
- Header guards
- Bullet proofing CMidiPacket
- The Big Six
- What is :
- What is a Markov chain?
- Arithmetic operations
- Bit manipulation \\
- Memory alignment
- The Big Six
- MIDI
- Strings
- Vector
- RegEx
- Additional code that can be used in Class project 1
5.2 Class
Announcement Class 5_3 is Quiz 1.
Quiz 1 w2020 review
Test rules
- Must be done in pencil
- Bring an eraser
- No calculators
- You are allowed to bring one 8.5x11 sheet of paper with HANDWRITTEN notes on each side
- Time limit is 60 minutes unless a disability exception has been made. Talk to me after class.
Terminal commands
What do these commands do
- cd
- pwd
- ls
- echo
- grep
- sed
- rm -fR *
C++
What is the difference between
- #include "file.h"
- #include <file.h>?
What is a.out?
What is the size in bytes of the following C++ types on mac
- char
- short
- int
- long
- above in bits
Write an example of each of these comment types
- anywhere on single line
- block comments
- conditional comments
operators
- +
- -
- *
- /
- %
- Multiple meanings
- +
- *
- &
Terms
- extern
- overloaded function
- narrowing cast
- default
- byte
- high nibble
- low nibble
Interface and implementation files
- which is .h and which is .cpp
- what's the purpose of a .h file
- what is a header guard and why are they used
Printing char
- Given this definition
- char c = 100;
- You want std::cout to print a number instead of the letter d.
- What are two C++ ways to do it?
Header guards
- Why are they used?
- Given two files myfile.h and myfile.cpp
- Write an example header guard used in myfile.h
- Write an example header guard used in myfile.cpp
- Write an example header guard used in myfile.h
Bullet proofing CMidiPacket
- We used three tests to check CMidiPacket for different types of errors
Explain what each test checked for.- googletest
- invariant_checking
- check_timestamps
The Big Six
Explain the purpose of
- Constructor
- Destructor
- Copy constructor
- Assignment operator
- Move copy constructor (you can ignore for test)
- Move assignment operator (you can ignore for test)
- Give an example of each using class object A and B.
- What does = default mean
What is :
- an overloaded function
- a virtual function
- a pure virtual function
- an abstract base class
What is a Markov chain?
Arithmetic operations
What is the output of each std::cout statement
void f1(int a) { a += 10; } void f2(int &a) { a += 10; } int main() { int x = 10; f1(x); std::cout << x << std::endl; // == f2(x); std::cout << x << std::endl; // == std::cout << x / 6 << std::endl; // ==; std::cout << x % 6 << std::endl; // ==; return 0; }
Bit manipulation \\
What is the output of each std::cout statement
#include <iostream> int main() { int x{0x9C}; std::cout << std::hex << (0xF0 & x) << std::endl; std::cout << (0x0F & x) << std::endl; }
Memory alignment
What does this code print
#include <iostream> struct MidiPacket { uint32_t timestamp; uint8_t status; uint8_t data1; uint8_t data2; }; int main() { std::cout << sizeof(MidiPacket) << std::endl; }
The Big Six
Explain the purpose of
- Constructor
- Destructor
- Copy constructor
- Assignment operator
- Move copy constructor (you can ignore for test)
- Move assignment operator (you can ignore for test)
- Give an example of each using class object A and B.
- What does = default mean
MIDI
What MIDI messages are used to emulate these properties of sound in MIDI
- pitch
- duration
- amplitude
- timbre
- location
status bytes and data bytes
- What is the range of a data byte
- What is the range of a status bytes
- How many MIDI channels are available for every status byte
- How do you tell what MIDI channel the status byte is sending to
What happens if you play these messages in MIDIDisply_DLS
# these are ok # piano patch 0 c0 0 # organ patch 0 c1 18 # There's a problem here # What happens? 0 90 60 100 500 91 64 100 1500 90 64 0
MIDI Note numbers
- Middle C is defined as MIDI note number 60.
- What is the MIDI note number of the next C on the piano keyboard one octave higher.
- What is the MIDI note number range of the full 88 key piano keyboard.
MIDI Messages
- How many instruments can play simultaneously?
- What two status bytes have only one data byte?
- How do you tell which MIDI channel the status byte affects?
- The NON (note on) message has data1 and data2 bytes. Explain what each one does.
- What are the two forms of a NOF (note off) message
- What status byte is used to change instruments
- What MIDI control message changes volume
- What MIDI control message changes pan
- What MIDI control message changes expression
- How many different ways are there to change how loud a note sounds? How do you choose which one to use?
Timestamps
CMidiPacket stores all timestamps using a tempo of 60 beats per minute or one beat every 1000 milliseconds. How would you recalculate the timestamps to send the messages at a tempo of 120 bpm, 30 bpm, and 90 bpm. Round to nearest integer if necessary.
Old timestamp tempo New timestamp 1000 60 1000 1800 60 1800 1000 120 1800 120 1000 30 1800 30 1000 90 1800 90
- CMidiPacket stores timestamps in strictly ascending numerical (chronological) order.
- Explain why sending of MIDI messages works best with delta times, or difference times.
Strings
- How do you find the length of a string?
- Given string s = "abcdefghi"
- what is s[4]
- what is the difference between s[10] and s.at(10)
Vector
- give vector v = {2, 4, 6, 8, 10}
- print the elements of vector v to std:cout using three different forms of a for loop.
- how do you add an element to a vector
- what does v.reserve(size_t n) do
- when you sort a vector what operator function is used.
RegEx
Your given a list of firstname lastname grade separated by spaces. There are no spaces in any name or grade. Write a find/replace regular expressing to reorder the list as grade lastname firstname
Additional code that can be used in Class project 1
Nothing in this section needs to be turned in as homework.
Setup
Execute these commands in Terminal
cd ~/cs312 mkdir hw52 cd hw52 mkdir class52_examples cd class52_examples touch ex1_function_object.cpp touch ex2_lambda_expression.cpp touch ex3_lambda_with_function.cpp
std::for_each
This lab will explore the std::for_each(…) function from the STL <algorithm> library.
std::for_each(_InputIterator __first, _InputIterator __last, _Function __f)
for_each(…) applies function __f to every element in an STL container (vector) over the iterator range __first to __last.
The _Function __f is a function object or a lambda expression.
- Function object
- a C++ class with one class method that overrides the () operator.
exists outside the for_each() expression.
also called a functor. - Lambda expression
- an anonymous function (not named).
similar to a function object.
can be defined inside the for_each() expression. - Lambda expression and named function
- an existing function called by a lambda expression.
Here are three examples that will help with the homework.
Function object
ex1_function_object.cpp
Example 1 is a simple function object that adds 3 to every element of a std::vector<int>
Copy/paste.
// ex1_funcion_object.cpp #include <iostream> #include <string> #include <vector> #include <algorithm> // Utility function void print_vec(const std::string msg, const std::vector<int> &v) { std::cout << msg; for (auto itr : v) std::cout << itr << " "; std::cout << std::endl; } // Function object override of operator() class plus3 { public: void operator()(int &n) { n += 3; } }; // example using for_each int main(int argc, char const *argv[]) { std::vector<int> v{1, 2, 3, 4, 5}; print_vec("Before:\t", v); std::for_each(v.begin(), v.end(), plus3()); print_vec("After:\t", v); }
Build and Run
# cd ~/cs312/hw52_je/class52_examples cl ex1_function_object.cpp && ./a.out
Output
Before: 1 2 3 4 5 After: 4 5 6 7 8
The plus3 function object
A function object is a simple class that overrides operator()(). The second () is the type of element that for_each() is iterating over. In order for the changed value to be returned it should be declared as a reference.
class plus3 { public: void operator()(int &n) { n += 3; } };
Lambda Expression
Example 2 converts the plus3 function object into a lambda expression.
Lambda expression for plus3
[](int &n) { n += 3; }
Syntax notes:
- []
- represents how local variables are captured
- [=] capture by value
- [&] capture by reference
- [] default, [=]?
- (int &n)
- the parameters to the lambda expression.
- { n += 3; }
- the lambda function body.
Identical to the body of operator()(int &n) in the function object class.
ex2_lambda_expression.cpp
Copy/paste
// ex2_lambda_expression.cpp #include <iostream> #include <vector> #include <algorithm> // Utility function void print_vec(const std::string msg, const std::vector<int> &v) { std::cout << msg; for (auto itr : v) std::cout << itr << " "; std::cout << std::endl; } // example using lambda expression int main(int argc, char const *argv[]) { std::vector<int> v{1, 2, 3, 4, 5}; print_vec("Before:\t", v); std::for_each(v.begin(), v.end(), [](int &n) { n += 3; }); print_vec("After:\t", v); }
Build and Run
# cd ~/cs312/hw52_je/class52_examples cl ex2_lambda_expression.cpp && ./a.out
Output
Before: 1 2 3 4 5 After: 4 5 6 7 8
Lambda expression with function.
Example 3 uses a lambda expression to call a regular function that takes parameters.
ex3_lambda_with_function.cpp
Copy/paste
// ex3_lambda_with_function.cpp #include <iostream> #include <vector> #include <algorithm> #include <cmath> // Utility function void print_vec(const std::string msg, const std::vector<int> &v) { std::cout << msg; for (auto itr : v) std::cout << itr << " "; std::cout << std::endl; } // regular function to scale MIDI data1 data2 values void scaleByPercent(int &n, float p, bool scaleUp = true) { if (scaleUp) n += (n * p); else n -= (n * p); // check for min max MIDI data1 data2 limits if (n > 127) n = 127; if (n < 0) n = 0; } // example lambda expression with function int main(int argc, char const *argv[]) { float pct{.10}; // data2 velocities std::vector<int> v{60, 70, 80, 90, 100, 127}; print_vec("Original:\t\t", v); std::for_each(v.begin(), v.end(), [=](int &n) { scaleByPercent(n, pct); }); print_vec("Scale up 10%:\t\t", v); std::for_each(v.begin(), v.end(), [=](int &n) { scaleByPercent(n, .9, false); }); print_vec("Scale down 90%:\t\t", v); }
Build and Run
# cd ~/cs312/hw52_je/class52_examples cl ex3_lambda_with_function.cpp && ./a.out
Output
Original: 60 70 80 90 100 127 Scale up 10%: 66 77 88 99 110 127 Scale down 90%: 6 7 8 9 11 12
Continue with the homework examples
The remaining hw52 assignments assume you have working copies of these classes (.h and .cpp) in your ~/cs312/common folder.
- hw331_CMidiPacket
- hw411_CMidiTrack
- hw411_randUtils
- hw423_CDelayMs
- hw425_CAppleMidiSynth
All homework examples involve using for_each() to modify a std::vector<CMidiPacket>.
c521_splitTracks
This first assignment will read in a MIDIDisplay file with three tracks and split them into individual CMidiTrack's based on the MIDI channel. The pentatonicTrio.txt file I've included is my output from hw426_CScalesTrio using the major pentatonic scale. You'll end up with four tracks to experiment with.
- v0 (soprano, channel 0, patch 11 vibraphone)
- v1 (alto, channel 1, patch 12 marimba)
- v2 (bass, channel 2, patch 32 acoustic bass)
- vplay (v0+v1+v2 sorted)
Files from hw521_splitTracks will be used in other hw52 homework.
Setup
Execute in Terminal
cd ~/cs312/hw52 mkdir hw521_splitTracks cd hw521_splitTracks mkdir build touch CMakeLists.txt touch pentatonic_trio.txt touch hw521_main.cpp touch hw521_splitTracks.cpp touch hw521_splitTracks.h
Copy paste these files into their vsCode counterparts. Using common folder files hw521_splitTracks built and ran without errors.
hw521_splitTracks.h
// hw521_splitTracks.h #ifndef HW521_SPLITTRACKS_H_ #define HW521_SPLITTRACKS_H_ #ifndef HW331_CMIDIPACKET_H_ #include "hw331_CMidiPacket.h" #endif #include <vector> #include <fstream> #include <string> using namespace CMP33; // pentatonic_trio.txt must be in parent folder of build folder extern std::vector<CMidiPacket> v0; extern std::vector<CMidiPacket> v1; extern std::vector<CMidiPacket> v2; extern void splitTracks(const std::string &filename); #endif // HW521_SPLITTRACKS_H_
hw521_splitTracks.cpp
#ifndef HW521_SPLITTRACKS_H_ #include "hw521_splitTracks.h" #endif #include <string> #include <fstream> using namespace CMP33; // sort into tracks std::vector<CMidiPacket> v0; std::vector<CMidiPacket> v1; std::vector<CMidiPacket> v2; void splitTracks(const std::string &filename) { std::fstream file; file.open(filename); if (!file.is_open()) { std::cout << filename << " could not be opened" << std::endl; } std::string line; while (getline(file, line)) { // std::cout << line << std::endl; CMidiPacket mp(line); // vplay.push_back(mp); if (mp.get_midi_channel() == 0) { v0.push_back(mp); } else if (mp.get_midi_channel() == 1) { v1.push_back(mp); } else if (mp.get_midi_channel() == 2) { v2.push_back(mp); } } }
hw521_main.cpp
#ifndef HW521_SPLITTRACKS_H_ #include "hw521_splitTracks.h" #endif #ifndef HW423_CDELAYMS_H_ #include "hw423_CDelayMs.h" #endif #ifndef HW425_CAPPLEMIDISYNTH_H_ #include "hw425_CAppleMidiSynth.h" #endif #include <fstream> using namespace CMP33; int main(int argc, char const *argv[]) { std::vector<CMidiPacket> vplay; splitTracks("../pentatonic_trio.txt"); std::copy(v0.begin(), v0.end(), std::back_inserter(vplay)); std::copy(v1.begin(), v1.end(), std::back_inserter(vplay)); std::copy(v2.begin(), v2.end(), std::back_inserter(vplay)); std::sort(vplay.begin(), vplay.end()); CDelayMs::s_tempo = 100; CAppleMidiSynth cams; for (auto itr : vplay) { cams.send(itr); std::cout << itr; } }
CMakeLists.txt
cmake_minimum_required(VERSION 3.5) set(app_NAME "hw521_splitTracks") project(${app_NAME}) set(HOME "/Users/je") set(COMMON "${HOME}/cs312/common") set(app_SOURCES ${COMMON}/hw331_CMidiPacket.cpp ${COMMON}/hw411_randUtils.cpp ${COMMON}/hw423_CDelayMs.cpp ${COMMON}/hw425_CAppleMidiSynth.cpp hw521_splitTracks.cpp hw521_main.cpp ) add_executable(${app_NAME} ${app_SOURCES}) target_include_directories(${app_NAME} PRIVATE ${COMMON}) target_compile_features(${app_NAME} PRIVATE cxx_std_17) target_compile_options(${app_NAME} PRIVATE -g -Wall) target_link_libraries(${PROJECT_NAME} PRIVATE "-framework AudioToolbox") target_link_libraries(${PROJECT_NAME} PRIVATE "-framework CoreMIDI") target_link_libraries(${PROJECT_NAME} PRIVATE "-framework CoreAudio") target_link_libraries(${PROJECT_NAME} PRIVATE "-framework CoreFoundation")
pentatonic_trio.txt
Note: This file must use tabs to separate the CMidiPacket data elements. Sometimes browsers change tabs to spaces behind the scenes. This file has tabs on my Mac using Chrome as the browser. You can change runs of spaces to tabs in vsCode using this regular expression.
Notes:
- [^0-9a-fA-F]+
- Brackets limit the search to digits 0 to 9 plus hex values a-f or A-F
The + after the brackets means 1 or more
The ^ inside the brackets negates the search, i.e. anything that isn't a digit or hex digit (spaces) - \t
- replace selection with \t, a tab character.
0 c0 11 0 c1 12 0 c2 32 0 b2 7 100 0 b0 7 100 0 b1 7 127 0 b0 10 0 0 b2 10 64 0 b1 10 127 0 92 40 65 0 91 62 100 0 90 86 100 333 81 62 0 333 80 86 0 333 91 60 100 333 90 88 100 667 82 40 0 667 80 88 0 667 92 38 65 667 90 84 100 1000 80 84 0 1000 90 93 100 1333 81 60 0 1333 80 93 0 1333 91 64 100 1333 90 91 100 1334 82 38 0 1334 92 43 65 1667 82 43 0 1667 92 38 65 2000 82 38 0 2000 80 91 0 2000 81 64 0 2000 92 48 65 2000 91 69 100 2000 90 88 100 2333 82 48 0 2333 81 69 0 2333 92 45 65 2333 91 67 100 2334 80 88 0 2334 90 88 100 2666 81 67 0 2666 91 67 100 2667 80 88 0 2667 90 84 100 3000 82 45 0 3000 92 43 65 3333 82 43 0 3333 92 40 65 3334 80 84 0 3334 90 88 100 3666 81 67 0 3666 82 40 0 3666 92 38 65 3666 91 64 100 3668 80 88 0 3668 90 86 100 4001 80 86 0 4001 90 96 100 4333 82 38 0 4333 81 64 0 4333 92 36 65 4333 91 60 100 4334 80 96 0 4334 90 93 100 4666 81 60 0 4666 91 62 100 4667 80 93 0 4667 90 91 100 5000 82 36 0 5000 92 36 65 5333 82 36 0 5333 81 62 0 5333 92 40 65 5333 91 67 100 5334 80 91 0 5334 90 91 100 5668 80 91 0 5668 90 88 100 6000 82 40 0 6000 92 40 65 6001 80 88 0 6001 90 93 100 6333 82 40 0 6333 81 67 0 6333 92 48 65 6333 91 72 100 6668 80 93 0 6668 90 91 100 7000 81 72 0 7000 82 48 0 7000 92 45 65 7000 91 72 100 7333 81 72 0 7333 91 69 100 7335 80 91 0 7335 90 88 100 7666 81 69 0 7666 91 67 100 7667 82 45 0 7667 92 40 65 7669 80 88 0 7669 90 86 100 8000 82 40 0 8000 92 38 65 8002 80 86 0 8002 90 86 100 8333 82 38 0 8333 81 67 0 8333 92 36 65 8333 91 64 100 8335 80 86 0 8335 90 84 100 9000 82 36 0 9000 92 36 65 9002 80 84 0 9002 90 84 100 9333 82 36 0 9333 81 64 0 9333 92 36 65 9333 91 60 100 9666 81 60 0 9666 91 62 100 9669 80 84 0 9669 90 88 100 10000 82 36 0 10000 92 40 65 10003 80 88 0 10003 90 96 100 10333 82 40 0 10333 81 62 0 10333 92 48 65 10333 91 69 100 10336 80 96 0 10336 90 96 100 10666 82 48 0 10666 92 45 65 10669 80 96 0 10669 90 93 100 11333 82 45 0 11333 81 69 0 11333 92 43 65 11333 91 69 100 11336 80 93 0 11336 90 91 100 11666 82 43 0 11666 92 43 65 12000 81 69 0 12000 91 72 100 12003 80 91 0 12003 90 88 100 12333 82 43 0 12333 81 72 0 12333 92 40 65 12333 91 69 100 12337 80 88 0 12337 90 86 100 12666 82 40 0 12666 81 69 0 12666 92 38 65 12666 91 67 100 12670 80 86 0 12670 90 86 100 12999 82 38 0 12999 92 36 65 13003 80 86 0 13003 90 84 100 13666 82 36 0 13666 81 67 0 13666 92 38 65 13666 91 64 100 13670 80 84 0 13670 90 86 100 13999 82 38 0 13999 92 38 65 14003 80 86 0 14003 90 84 100 14336 80 84 0 14336 90 86 100 14666 81 64 0 14666 82 38 0 14666 92 43 65 14666 91 64 100 14999 82 43 0 14999 92 40 65 15003 80 86 0 15003 90 86 100 15333 81 64 0 15333 91 62 100 15337 80 86 0 15337 90 91 100 15666 82 40 0 15666 92 40 65 15670 80 91 0 15670 90 96 100 15999 82 40 0 15999 92 38 65 16000 81 62 0 16000 91 60 100 16003 80 96 0 16003 90 93 100 16333 81 60 0 16333 91 64 100 16336 80 93 0 16336 90 91 100 16666 82 38 0 16666 92 36 65 17003 80 91 0 17003 90 91 100 17333 81 64 0 17333 82 36 0 17333 92 40 65 17333 91 64 100 17337 80 91 0 17337 90 88 100 17666 82 40 0 17666 92 45 65 17670 80 88 0 17670 90 86 100 18003 80 86 0 18003 90 84 100 18333 82 45 0 18333 81 64 0 18333 92 45 65 18333 91 69 100 18336 80 84 0 18336 90 88 100 18666 82 45 0 18666 92 48 65 19000 81 69 0 19000 91 72 100 19003 80 88 0 19003 90 88 100 19333 82 48 0 19333 92 45 65 19337 80 88 0 19337 90 93 100 19667 81 72 0 19667 91 69 100 19670 80 93 0 19670 90 96 100 20000 82 45 0 20000 81 69 0 20000 92 43 65 20000 91 62 100 20003 80 96 0 20003 90 93 100 20333 81 62 0 20333 82 43 0 20333 92 40 65 20333 91 60 100 20336 80 93 0 20336 90 91 100 20666 81 60 0 20666 91 67 100 21000 82 40 0 21000 92 40 65 21003 80 91 0 21003 90 88 100 21333 82 40 0 21333 92 38 65 21337 80 88 0 21337 90 88 100 21666 81 67 0 21666 91 72 100 21670 80 88 0 21670 90 86 100 22000 82 38 0 22000 92 36 65 22003 80 86 0 22003 90 84 100 22336 80 84 0 22336 90 91 100 22666 81 72 0 22666 91 72 100 22667 82 36 0 22667 92 40 65 23000 82 40 0 23000 92 45 65 23003 80 91 0 23003 90 96 100 23333 81 72 0 23333 91 72 100 23337 80 96 0 23337 90 96 100 23666 81 72 0 23666 91 69 100 23667 82 45 0 23667 92 45 65 23670 80 96 0 23670 90 96 100 23999 81 69 0 23999 91 67 100 24000 82 45 0 24000 92 48 65 24003 80 96 0 24003 90 93 100 24332 81 67 0 24332 91 64 100 24667 82 48 0 24667 92 45 65 24670 80 93 0 24670 90 91 100 25332 81 64 0 25332 91 64 100 25334 82 45 0 25334 92 43 65 25337 80 91 0 25337 90 88 100 25667 82 43 0 25667 92 40 65 25671 80 88 0 25671 90 86 100 25999 81 64 0 25999 91 62 100 26004 80 86 0 26004 90 86 100 26332 81 62 0 26332 91 60 100 26334 82 40 0 26334 92 40 65 26337 80 86 0 26337 90 84 100 26665 81 60 0 26665 91 67 100 26667 82 40 0 26667 92 38 65 27004 80 84 0 27004 90 88 100 27334 82 38 0 27334 92 36 65 27338 80 88 0 27338 90 86 100 27665 81 67 0 27665 91 62 100 27671 80 86 0 27671 90 84 100 28001 82 36 0 28001 92 43 65 28004 80 84 0 28004 90 84 100 28334 82 43 0 28334 92 48 65 28665 81 62 0 28665 91 62 100 28671 80 84 0 28671 90 93 100 29001 82 48 0 29001 92 48 65 29005 80 93 0 29005 90 93 100 29332 81 62 0 29332 91 72 100 29334 82 48 0 29334 92 48 65 29338 80 93 0 29338 90 96 100 29665 81 72 0 29665 91 69 100 29671 80 96 0 29671 90 93 100 29998 81 69 0 29998 91 67 100 30001 82 48 0 30001 92 45 65 30004 80 93 0 30004 90 93 100 30331 81 67 0 30331 91 64 100 30668 82 45 0 30668 92 43 65 30671 80 93 0 30671 90 91 100 31001 82 43 0 31001 92 40 65 31005 80 91 0 31005 90 88 100 31331 81 64 0 31331 91 64 100 31338 80 88 0 31338 90 86 100 31668 82 40 0 31668 92 40 65 31671 80 86 0 31671 90 84 100 31998 81 64 0 31998 91 62 100 32001 82 40 0 32001 92 45 65 32004 80 84 0 32004 90 84 100 32665 81 62 0 32665 91 60 100 32668 82 45 0 32668 92 43 65 32671 80 84 0 32671 90 96 100 32998 81 60 0 32998 91 69 100 33001 82 43 0 33001 92 40 65 33005 80 96 0 33005 90 86 100 33331 81 69 0 33331 91 69 100 33338 80 86 0 33338 90 96 100 33668 82 40 0 33668 92 40 65 33671 80 96 0 33671 90 93 100 34001 82 40 0 34001 92 38 65 34004 80 93 0 34004 90 91 100 34331 81 69 0 34331 91 64 100 34334 82 38 0 34334 92 36 65 34671 80 91 0 34671 90 91 100 34998 81 64 0 34998 91 72 100 35001 82 36 0 35001 92 45 65 35005 80 91 0 35005 90 88 100 35331 81 72 0 35331 91 69 100 35334 82 45 0 35334 92 45 65 35338 80 88 0 35338 90 86 100 35664 81 69 0 35664 91 67 100 35671 80 86 0 35671 90 84 100 35997 81 67 0 35997 91 64 100 36001 82 45 0 36001 92 36 65 36004 80 84 0 36004 90 96 100 36334 82 36 0 36334 92 48 65 36671 80 96 0 36671 90 96 100 36997 81 64 0 36997 91 64 100 37001 82 48 0 37001 92 45 65 37005 80 96 0 37005 90 93 100 37338 80 93 0 37338 90 96 100 37664 81 64 0 37664 91 62 100 37668 82 45 0 37668 92 43 65 37671 80 96 0 37671 90 93 100 38001 82 43 0 38001 92 40 65 38004 80 93 0 38004 90 91 100 38331 81 62 0 38331 91 60 100 38664 81 60 0 38664 91 60 100 38668 82 40 0 38668 92 40 65 38671 80 91 0 38671 90 88 100 39001 82 40 0 39001 92 38 65 39005 80 88 0 39005 90 88 100 39334 82 38 0 39334 92 36 65 39338 80 88 0 39338 90 86 100 39664 81 60 0 39664 91 62 100 39671 80 86 0 39671 90 84 100 40001 82 36 0 40001 92 48 65 40004 80 84 0 40004 90 93 100 40334 82 48 0 40334 92 48 65 40664 81 62 0 40664 91 60 100 40671 80 93 0 40671 90 84 100 41001 82 48 0 41001 92 45 65 41005 80 84 0 41005 90 84 100 41334 82 45 0 41334 92 48 65 41338 80 84 0 41338 90 96 100 41664 81 60 0 41664 91 72 100 41671 80 96 0 41671 90 93 100 42001 82 48 0 42001 92 45 65 42004 80 93 0 42004 90 91 100 42331 81 72 0 42331 91 69 100 42664 81 69 0 42664 91 69 100 42668 82 45 0 42668 92 43 65 42671 80 91 0 42671 90 88 100 43001 82 43 0 43001 92 40 65 43005 80 88 0 43005 90 88 100 43338 80 88 0 43338 90 86 100 43664 81 69 0 43664 91 67 100 43668 82 40 0 43668 92 40 65 43671 80 86 0 43671 90 84 100 44001 82 40 0 44001 92 38 65 44004 80 84 0 44004 90 86 100 44334 82 38 0 44334 92 36 65 44664 81 67 0 44664 91 64 100 44671 80 86 0 44671 90 86 100 45001 82 36 0 45001 92 43 65 45005 80 86 0 45005 90 96 100 45334 82 43 0 45334 92 36 65 45338 80 96 0 45338 90 96 100 45664 81 64 0 45664 91 62 100 45671 80 96 0 45671 90 93 100 46001 82 36 0 46001 92 36 65 46004 80 93 0 46004 90 91 100 46331 81 62 0 46331 91 62 100 46334 82 36 0 46334 92 48 65 46664 81 62 0 46664 91 60 100 46671 80 91 0 46671 90 88 100 47001 82 48 0 47001 92 45 65 47005 80 88 0 47005 90 88 100 47338 80 88 0 47338 90 86 100 47664 81 60 0 47664 91 62 100 47668 82 45 0 47668 92 43 65 47671 80 86 0 47671 90 84 100 48001 82 43 0 48001 92 40 65 48004 80 84 0 48004 90 88 100 48664 81 62 0 48664 91 60 100 48668 82 40 0 48668 92 40 65 48671 80 88 0 48671 90 86 100 49001 82 40 0 49001 92 38 65 49005 80 86 0 49005 90 96 100 49338 80 96 0 49338 90 96 100 49664 81 60 0 49664 91 72 100 49668 82 38 0 49668 92 36 65 49671 80 96 0 49671 90 93 100 50331 81 72 0 50335 82 36 0 50338 80 93 0
Build and run
je$ cd build je$ cmake .. && make && ./splitTracks_hw521
Output
The CMidiPacket output should be displayed as the sound is playing.
c522_setVelocity
The bass track (v2) in pentatonic_trio.mp3 is too soft. Let's use for_each(…) to fix it. We'll need a function object to change the velocity, data2 of a NON message.
Setup
cd ~/cs312/hw52 mkdir hw522_setVelocity cd hw522_setVelocity mkdir build cp ~/cs312/hw52/hw521_splitTracks/CMakeLists.txt . cp ~/cs312/hw52/hw521_splitTracks/hw521_main.cpp ./hw522_main.cpp ## Remember to change boilerplate for hw522_main.cpp
CMakeLists.txt
Insert this line
set(HW521 "~/cs312/hw52/hw521_splitTracks")
Changes to CMakeLists.txt
- set app_NAME to hw522_setVelocity
- create HW521 variable shown above
- fix pathname to hw521_splitTracks.cpp
- rename hw521_main.cpp
- add variable HW521 to target_include_directories
hw522_main.cpp
Copy/paste/fix.
#ifndef HW521_SPLITTRACKS_H_ #include "hw521_splitTracks.h" #endif #ifndef HW423_CDELAYMS_H_ #include "hw423_CDelayMs.h" #endif #ifndef HW425_CAPPLEMIDISYNTH_H_ #include "hw425_CAppleMidiSynth.h" #endif #include <fstream> using namespace CMP33; class SetVelocity { public: void operator()(CMidiPacket &mp) { std::cout << "You need to implement SetVelocity function object\n"; } }; int main(int argc, char const *argv[]) { std::vector<CMidiPacket> vplay; /* you need to call splitTracks with a relative pathname This was used in hw521_main: splitTracks("../pentatonic_trio.txt"); In this case pentatonic_trio.txt was in the parent folder from where the executable was located (build). So ../ referred to the parent folder of build In hw522_setVelocity the pentatonic_trio.txt file is still inside hw521_splitTracks Hint: ../../ is the parent of the parent folder */ // call splitTracks( RELATIVE_PATHNAME ); // this is from hw521_main.cpp and will cause an error in hw522_main.cpp splitTracks("../pentatonic_trio.txt"); // ADD std::for_each(v2.begin(), v2.end(), SetVelocity()); // END ADD std::copy(v0.begin(), v0.end(), std::back_inserter(vplay)); std::copy(v1.begin(), v1.end(), std::back_inserter(vplay)); std::copy(v2.begin(), v2.end(), std::back_inserter(vplay)); std::sort(vplay.begin(), vplay.end()); // Uncomment when ready to test #if 0 CDelayMs::s_tempo = 100; CAppleMidiSynth cams; for (auto itr : vplay) { cams.send(itr); std::cout << itr; } #endif return 0; }
c523_setVelocity_lambda
Convert the setVelocity function object to a lambda expression and use the lambda expression inside the for_each() statement.
Setup
cd ~/cs312/hw52 mkdir hw523_setVelocity_lambda cd hw523_setVelocity_lambda mkdir build cp ~/cs312/hw52/hw522_setVelocity/hw522_main.cpp hw523_main.cpp cp ~/cs312/hw52/hw522_setVelocity/CMakeLists.txt . ## Remember to change boilerplate for hw522_main.cpp
CMakeLists.txt
Changes to CMakeLists.txt
- set app_NAME to hw523_setVelocity_lambda
- rename hw522_main.cpp
hw523_main.cpp
Copy/paste/fix.
#ifndef HW521_SPLITTRACKS_H_ #include "hw521_splitTracks.h" #endif #ifndef HW423_CDELAYMS_H_ #include "hw423_CDelayMs.h" #endif #ifndef HW425_CAPPLEMIDISYNTH_H_ #include "hw425_CAppleMidiSynth.h" #endif #include <fstream> using namespace CMP33; // setVelocity function object removed int main(int argc, char const *argv[]) { std::vector<CMidiPacket> vplay; // What worked in hw522_ should also work for hw523_ //splitTracks("../pentatonic_trio.txt"); // Uncomment and add lambda function // std::for_each(v2.begin(), v2.end(), LAMBDA_FUNCTION_HERE); // Uncomment when split tracks worked #if 0 std::copy(v0.begin(), v0.end(), std::back_inserter(vplay)); std::copy(v1.begin(), v1.end(), std::back_inserter(vplay)); std::copy(v2.begin(), v2.end(), std::back_inserter(vplay)); std::sort(vplay.begin(), vplay.end()); CDelayMs::s_tempo = 100; CAppleMidiSynth cams; for (auto itr : vplay) { cams.send(itr); std::cout << itr; } #endif return 0; }
c524_accentEveryNnotes
Use a lambda expression to call regular function to accent every N notes.
Setup
cd ~/cs312/hw52 mkdir hw524_accentEveryNnotes cd hw524_accentEveryNnotes mkdir build cp ~/cs312/hw52/hw523_setVelocity_lambda/hw523_main.cpp hw524_main.cpp cp ~/cs312/hw52/hw523_setVelocity_lambda/CMakeLists.txt . ## Remember to change boilerplate for hw522_main.cpp
CMakeLists.txt
Changes to CMakeLists.txt
- set app_NAME to hw524_accentEveryNnotes
- rename hw523_main.cpp
hw523_main.cpp
Copy/paste/fix.
// hw524_main.cpp #ifndef HW521_SPLITTRACKS_H_ #include "hw521_splitTracks.h" #endif #ifndef HW423_CDELAYMS_H_ #include "hw423_CDelayMs.h" #endif #ifndef HW425_CAPPLEMIDISYNTH_H_ #include "hw425_CAppleMidiSynth.h" #endif #include <fstream> using namespace CMP33; void AccentEveryNnotes(CMidiPacket &mp, int modN, int loud, int soft) { /* create a static variable to keep a running count of every time this function has been called. I called it count. if mp is a NOF return; else if mp is a NON set data2 velocity to soft; if count mod N is zero set data2 velocity to loud increment count */ } int main(int argc, char const *argv[]) { std::vector<CMidiPacket> vplay; splitTracks("../../hw521_splitTracks/pentatonic_trio.txt"); // set velocity for v2 using either method of hw52_ or hw63_ // write a lambda expression to AccentEveryNnotes in for_each() for v0 // write a lambda expression to AccentEveryNnotes in for_each() for v1 // write a lambda expression to AccentEveryNnotes in for_each() for v2 std::copy(v0.begin(), v0.end(), std::back_inserter(vplay)); std::copy(v1.begin(), v1.end(), std::back_inserter(vplay)); std::copy(v2.begin(), v2.end(), std::back_inserter(vplay)); std::sort(vplay.begin(), vplay.end()); CDelayMs::s_tempo = 100; CAppleMidiSynth cams; // you could play individual tracks like (auto itr : v2) for (auto itr : vplay) { cams.send(itr); std::cout << itr; } return 0; }
Ideas for for_each()
std::for_each(v0.begin(), v0.end(), [](CMidiPacket &mp) { AccentEveryNnotes(mp, 3, 127, 65); }); std::for_each(v1.begin(), v1.end(), [](CMidiPacket &mp) { AccentEveryNnotes(mp, 3, 127, 65); }); std::for_each(v2.begin(), v2.end(), [](CMidiPacket &mp) { AccentEveryNnotes(mp, 3, 127, 65); });
std::for_each(v0.begin(), v0.end(), [](CMidiPacket &mp) { AccentEveryN(mp, 6, 127, 65); }); std::for_each(v1.begin(), v1.end(), [](CMidiPacket &mp) { AccentEveryN(mp, 9, 127, 65); }); std::for_each(v2.begin(), v2.end(), [](CMidiPacket &mp) { AccentEveryN(mp, 3, 127, 65); });
std::for_each(v0.begin(), v0.end(), [](CMidiPacket &mp) { AccentEveryN(mp, 3, 127, 65); }); std::for_each(v1.begin(), v1.end(), [](CMidiPacket &mp) { AccentEveryN(mp, 7, 127, 65); }); std::for_each(v2.begin(), v2.end(), [](CMidiPacket &mp) { AccentEveryN(mp, 4, 127, 65); });
Submission Format
Nothing needs to be turned in. You can use examples in your class project 1 if you choose to.