4.3 Class
CS 312 Audio Programming Winter 2020

Table of Contents

4.3 Lab Class

Homework notes

Assuming your hand-in folder contained this structure for hw331_checktimestamps

/Users/je/_aGraded312/<HANDIN_FOLDER_NAME>
├── bin
│   └── checkTimestamps
├── common
│   ├── hw332_CMidiPacket.cpp
│   └── hw332_CMidiPacket.h
└── hw33
    ├── hw331_checkTimestamps
    │   ├── CMakeLists.txt
    │   ├── build
    │   ├── hw331_checkTimestamps.cpp
    │   ├── hw331_checkTimestamps.h
    │   ├── hw331_main.cpp
    │   └── output.txt
    └── hw332_test_invariants
        ├── CMakeLists.txt
        ├── build
        ├── hw332_main.cpp
        ├── hw332_testInvariants.cpp
        └── hw332_testInvariants.h

I copy your hand-in folder to my Mac inside a folder I call _aGraded312.
This is the CMakeLists.txt file I use to compile your assignment.

cmake_minimum_required(VERSION 2.8)
set(APPNAME "checkTimestamps")
project(${APPNAME})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -Wall ")

set(HOME "/Users/je/_aGraded312/<HANDIN_FOLDER_NAME")
set(COMMON "${HOME}/common")

set(SOURCE_FILES
  ${COMMON}/hw332_CMidiPacket.cpp
  hw331_checkTimestamps.cpp
  hw331_main.cpp
  )

include_directories(${COMMON})
add_executable(${APPNAME} ${SOURCE_FILES})

You should be able compile your hand-in folder before turning it in by modifying the HOME pathname.

Drum Sequencer

Overview

Hardware and software based sequencers are commonly based on a matrix of rows and columns. Apple's Drum Beat Sequencer is shown below. Each row represents a single drum sound and is divided into 16 columns. Columns represent equally spaced units of time called a tick (like a clock tick.) Ticks move uniformly left to right and apply to all rows in that column. Any row/column intersection can be turned on or off. At every tick an "on" state plays a sound. Off states make no sound. Ticks loop back to the start. After tick 16 the sequence restarts at tick 1. This continues until the user stops the drum machine.

Apple Garage Band IOS Beat Sequencer is an 8x16 software sequencer
8 rows x 16 columns.

ChromeScreenSnapz001.png

Columns
  • The 16 columns are separated by uniformly spaced timestamps called a ticks.
  • The tick rate determines the playback speed.
  • A short tick rates play fast and long tick rates plays slow.
  • The entire column is played on each tick.
  • If a cell in the column is highlighted it is played, otherwise it's ignored.
  • We'll use the tick rate of 250 ms or one fourth of our standard 1000 ms beat unit.
Rows
  • Each row represents a single drum sound on one MIDI channel 9.
  • A different drum sound is assigned to each row.
  • Hilighted cells in a row indicate when a sound is played.
  • The row contains four beats separated by thick vertical bars
  • Each beat divided into 4 subdivisions.

Apple icons for rows 1-8

  1. Bass drum
  2. Snare drum
  3. Clap
  4. Closed Hi-hat
  5. Open Hi-hat
  6. Low Tom
  7. High Tom
  8. Sticks

Use your gmdrums tool to lookup these drum note numbers.
For Sticks you can substitute any of these:
side stick, claves, high wood block, low wood block.

My mp3 output
This is the output I get using the drum sounds and pattern sequence shown in the above picture.

hw431_drumMachine_75bpm.mp3

CS312 Drum Sequencer

We'll implement two classes, a CDrumMachine class and a CDrumTrack class.

Should CDrumTrack be a subclass of CDrumMachine or a member variable of CDrumTrack?

  • There is a well known method to help deciding using "is a" vs. "has a" terminology.
  • If you think "CDrumTrack "is a" drum machine you'd implement it as a subclass.
  • If you think "CDrumMachine "has a" drum track you'd implement it as a member variable.
  • The "has a" method is clearly the correct choice.
  • In fact CDrumMachine "has a" eight CDrumTrack variables.
class CDrumMachine
  • contains a vector of eight CDrumTracks
  • contains the drum note
class CDrumTrack
  • CDrumTrack is a subclass of CMidiTrack that writes the MIDI messages needed for one row.
  • The drum sound used for each row cannot be changed while playing.
  • Drum tracks use delta time, the time difference between tick(N) and tick(N-1).

Implementation notes
The sound on/off states can be represented using a std::string of ones and zeros.

Idea 1 - One string per row
These are the strings representing the on/off states of the IOS drum machine shown above.

  • "1000100010001000" for row 1
  • "0001001000010010" for row 2
  • "0000000000000010" for row 3
  • etc.
Cons
It's hard to see where the four beats per row are using the long string representation.
It does not allow for future implementations to have three or five+ notes per beat.

Idea 2 - One string per beat
In the IOS Drum Machine picture thick vertical bars separated each beat.
We can divide each row into four small strings, one for each beat.

  • "1000", "1000", "1000", "1000" for row 1
  • "0001", "0010", "0001", "0010" for row 2
  • "0000", "0000", "0000", "0010" for row 3
  • etc.
Pros
The four beats in each row are clear
The number of subdivisions can vary as long as they add up to 1000ms.
2 notes per beat {500 500}
3 notes per beat {334 333 333}
4 notes per beat {250 250 250 250} <== the one we'll be using
5 notes per beat {200 200 200 200 200}
6 notes per beat {167, 167, 166, 167, 167, 166}
7 notes per beat {143, 143, 143, 143, 143, 142, 143}
8 notes per beat {125 125 125 125 125 125 125 125}
Cons
There is some redundancy, for example one beat with 2 subdivisions could be represented by
"11" or "1010" or "100100" or "10001000".
They all would be equivalent to durations {500 500} the only difference would be the duration of the note which is turned off at the next zero.

Apple icons for rows 1-8

  1. Bass drum
  2. Snare drum
  3. Clap
  4. Closed Hi-hat
  5. Open Hi-hat
  6. Low Tom
  7. High Tom
  8. Sticks

Use your gmdrums tool to lookup these drum note numbers.

My mp3 output

hw431_drumMachine_75bpm.mp3

Homework 4.3

hw431_drumMachine

In this assignment you'll implement the code needed to play the sound for each hilighted cell in a column during N trips (loops) through the sixteen column sequence.

Setup
Execute in Terminal.

cd $HOME312/cs312
mkdir hw43
cd hw43
mkdir hw431_drumMachine
cd hw431_drumMachine
mkdir build
touch CMakeLists.txt
# create files and add boilerplate
touch hw431_CDrumTrack.h
touch hw431_CDrumTrack.cpp
touch hw431_CDrumMachine.h
touch hw431_CDrumMachine.cpp
touch hw431_main.cpp

Copy this code into their appropriate files.

hw431_CDrumMachine.h
Do not modify.

// hw431_CDrumMachine.h
#ifndef hw431_CDRUMMACHINE_H_
#define hw431_CDRUMMACHINE_H_

#ifndef hw431_CDRUMTRACK_H_
#include "hw431_CDrumTrack.h"
#endif

#include <cstdint>
#include <vector>

// DO NOT MODIFY

// You can add others
// Look up drum note numbers using the CS312 tool gmdrums
// Note: zero is not the correct number
const uint8_t kBASS_DRUM = 36;
const uint8_t kSNARE_DRUM = 0;
const uint8_t kCLAP = 0;
const uint8_t kCLOSED_HIHAT = 0;
const uint8_t kOPEN_HIHAT = 0;
const uint8_t kLOW_TOM = 0;
const uint8_t kHIGH_TOM = 0;
const uint8_t kSIDE_STICK = 0;
const uint8_t kWOOD_BLOCK = 0;

// DO NOT MODIFY class CDrumMachine
class CDrumMachine
{
public:
  // This vector holds all eight drum tracks (rows)
  std::vector<CDrumTrack> vDrumTracks;

  // the big 6 are all default constructed
  void make_track(const uint8_t note, const std::vector<std::string> &pats);
};

#endif // hw431_CDRUMMACHINE_H_

CDrumMachine.cpp
Do not modify.

// hw431_CDrumMachine.cpp
#ifndef hw431_CDRUMMACHINE_H_
#include "hw431_CDrumMachine.h"
#endif

// DO NOT MODIFY

void CDrumMachine::make_track(const uint8_t note, const std::vector<std::string> &pats)
{
  CDrumTrack dt;
  dt.init_note_pats(note, pats);
  vDrumTracks.push_back(dt);
}

hw431_CDrumTrack.h
Do not modify.

// hw431_CDrumTrack.h
#ifndef hw431_CDRUMTRACK_H_
#define hw431_CDRUMTRACK_H_

#ifndef hw423_CMIDITRACK_H_
#include "hw423_CMidiTrack.h"
#endif

#include <iostream>
#include <string>
#include <cstdint>

// DO NOT MODIFY

class CDrumTrack : public CMidiTrack
{
private:
  uint8_t drum_note;
  std::vector<std::string> vbeat_pattern;
  std::vector<uint32_t> vbeat_dur;

  void write_onebeat(std::string pat);
  void write_beats();

public:
  int beat_num;

  CDrumTrack();
  virtual ~CDrumTrack() = default;
  CDrumTrack(const CDrumTrack &) = default;
  CDrumTrack(CDrumTrack &&) = default;
  CDrumTrack &operator=(const CDrumTrack &) = default;
  CDrumTrack &operator=(CDrumTrack &&) = default;

  void init_note_pats(const uint8_t note, const std::vector<std::string> &pats);

  int getDrumNote() const { return drum_note; }
  void setDrumNote(const int &n) { drum_note = n; };
  int getBeatNum() const { return beat_num; }
  void setBeatNum(const int &m) { beat_num = m; };

  void write_track();
  void write_track(int num_loops);
};

#endif // hw431_CDRUMTRACK_H_

Implementation files

These two files are partially done with sections you have to complete.

hw431_main.cpp Copy/paste. You complete.

// hw431_main.cpp
#ifndef hw431_CDRUMACHINE_H_
#include "hw431_CDrumMachine.h"
#endif

#ifndef hw423_CMIDITRACK_H
#include "hw423_CMidiTrack.h"
#endif

#ifndef HW421_CDELAYMS_H_
#include "hw421_CDelayMs.h"
#endif

#ifndef HW422_CAPPLEMIDISYNTH_H_
#include "hw422_CAppleMidiSynth.h"
#endif

#include <iostream>

using namespace CMP33;

int main()
{
  // declare the playback vector
  std::vector<CMidiPacket> vplay;

  // create the drum machine
  CDrumMachine dm;

  // stuff each row into the dm.tracks vector
  dm.make_track(kBASS_DRUM, {"1000", "1000", "1000", "1000"});
  // ... 7 more rows to go
  // figure them out from the picture of Apple's Drum Beat Sequencer picture on the web page
  std::cout << "main(): dm.make_track() 7 more rows to go\n";

  std::cout << "main(): you need to implement the for loop\n";
  for (auto n = 0; n < dm.vDrumTracks.size(); ++n)
  {
    dm.vDrumTracks[n].write_track(4); // repeat each row 4x
    // use std::copy(...) to stuff each of the eight vDrumTracks[n] into vplay
    std::cout << "main(): use std::copy(...) to stuff every vDrumTracks[n] into vplay\n";
  }
  sort(vplay.begin(), vplay.end());

  // use std::sort(...) to sort vplay
  std::cout << "main(): use std::sort(...) to sort vplay\n";

  // write vplay to std::cout
  std::cout << "main(): write vplay to std::cout\n";

  // set the CDelayMs::s_tempo, try 75
  std::cout << "main(): set the CDelayMs::s_tempo to 75\n";

  CDelayMs::s_tempo = 75;
  CAppleMidiSynth ams;
  // ams.send(vplay);
};

CDrumTrack.cpp

// hw431_CDrumTrack.cpp
#ifndef hw431_CDRUMTRACK_H_
#include "hw431_CDrumTrack.h"
#endif

CDrumTrack::CDrumTrack() : CMidiTrack(0, 0, 0, 0, 0, 0, 0)
{
  drum_note = 0;
  vbeat_pattern = {"0000", "0000", "0000", "0000"};
  vbeat_dur = {250, 250, 250, 250};
  beat_num = 0;
}

void CDrumTrack::init_note_pats(const uint8_t note, const std::vector<std::string> &pats)
{
  drum_note = note;
  vbeat_pattern = {pats};
}

void CDrumTrack::write_onebeat(std::string pat)
{
  /* 
  beat_num keeps a running count of the drum_machine ticks.
  In one trip through a drum_machine row, beat_num's will be 0, 1, 2, ... 14, 15
  In four trips through a drum_machine row, the starting beat_num of each repeat will be 0, 16, 32, 48
  The timestamp of each beat_num = beat_num * 1000
  vbeat_dur is a vector of 4 timestamps representing the duration of each beat subdivision {250,250,250,250}
  vbeat_pattern is a vector of 4 strings representing the on/off state of each beat subdivision {"1000","1000","1000","1000"}
  pat is one element of the vbeat_pattern vector representing the four subdivisions of a single beat like "1010".
  vbeat_dur.size() == vbeat_pattern.size() == 4 elemenets in each vector
  pat.size() == 4 (each element of vbeat_pattern has string length == 4)
  Every "1" in pat sends a NON message and must be matched with a n NOF 1ms before the next beat subdivision starts.
  Every "0" in pat is ignored for NON/NOF 
  The timestamp of each beat subdivision is updated by its duration for both "1" and "0".
  Increment beat_num when all four ones and zeros of the beat subdivision have been processed
 */
  std::cout << "CDrumTrack::write_onebeat(std::string pat) not implementated\n";
}

void CDrumTrack::write_beats()
{
  int subdivs = vbeat_pattern.size(); // is always be 4 for this drum machine
  for (int ix = 0; ix < subdivs; ++ix)
    write_onebeat(vbeat_pattern.at(ix));
}

void CDrumTrack::write_track()
{
  write_beats();
}

void CDrumTrack::write_track(int num_loops)
{
  for (auto ix = 0; ix < num_loops; ++ix)
    write_track();
}

Build and run using CMake
CMakeLists.txt

cmake_minimum_required(VERSION 3.5)
set(APPNAME "drum_machine")
project(${APPNAME})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -Wall ")
# you finish

SOURCE_FILES for cmake

common folder
├── hw332_CMidiPacket.cpp
├── hw423_CMidiTrack.cpp
├── hw421_CDelayMs.cpp
└── hw422_CAppleMidiSynth.cpp

hw431_drumMachine folder
├── hw431_CDrumMachine.cpp
├── hw431_CDrumTrack.cpp
└── hw431_main.cpp

Build and run
You'll need to write code for

hw431_CDrumTrack.cpp
write_onebeat(…)
hw431_main.cpp
first drumTrack is shown
you need 7 more

Everything else remains unchanged.

Output
You'll get several messages.
As you write the missing code delete the std::cout messages that tell you what to do.
Continue development using Xcode as described below.

je$ ./drum_machine
main(): dm.make_track() 7 more rows to go
main(): you need to implement the for loop
CDrumTrack::write_onebeat(std::string pat) not implementated
CDrumTrack::write_onebeat(std::string pat) not implementated
CDrumTrack::write_onebeat(std::string pat) not implementated
CDrumTrack::write_onebeat(std::string pat) not implementated
CDrumTrack::write_onebeat(std::string pat) not implementated
CDrumTrack::write_onebeat(std::string pat) not implementated
CDrumTrack::write_onebeat(std::string pat) not implementated
CDrumTrack::write_onebeat(std::string pat) not implementated
CDrumTrack::write_onebeat(std::string pat) not implementated
CDrumTrack::write_onebeat(std::string pat) not implementated
CDrumTrack::write_onebeat(std::string pat) not implementated
CDrumTrack::write_onebeat(std::string pat) not implementated
CDrumTrack::write_onebeat(std::string pat) not implementated
CDrumTrack::write_onebeat(std::string pat) not implementated
CDrumTrack::write_onebeat(std::string pat) not implementated
CDrumTrack::write_onebeat(std::string pat) not implementated
main(): use std::copy(...) to stuff every vDrumTracks[n] into vplay
main(): use std::sort(...) to sort vplay
main(): write vplay to std::cout
main(): set the CDelayMs::s_tempo to 75
CAppleMidiSynth() success

hw431_drumMachine - Xcode

We'll continue developing the drum_machine project using Apple's development system Xcode. It has an excellent Debugger that allows you to trace into function calls and examine variables as drum_machine is running. It's an excellent way to trace through an unfamiliar program to figure out how it works.

When I was creating this assignment I relied on the Xcode debugger to get the write_onebeat(…) function in hw431_CDrumTrack.cpp working correctly. It's the trickiest part of this homework.

Setup
CMake can generate a ready to run Xcode project file using these commands.
You have to start with an empty build folder.

Execute these commands.
If you haven't created the emptyBuildFolder.sh script (week 2.2) and copied it to your course bin folder do it now.
Note: -4 points if it's not there and working.

cd $HOME312/cs312/hw43
cp -R  hw431_drumMachine ./hw431_drumMachine_xcode
cd hw431_drumMachine_xcode
cd build
emptyBuildFolder.sh
cmake .. -G Xcode

Output

je$ cmake .. -G Xcode
-- The C compiler identification is AppleClang 10.0.1.10010046
-- The CXX compiler identification is AppleClang 10.0.1.10010046
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/je/cs312/_cs312/cs312/hw43/hw431_drumMachine_xcode/build

After cmake .. -G Xcode has finished the Xcode project file will be in the build folder.

xcode2.png

Open the Xcode project
Either double click in Finder
or
Open from vsCode Terminal.

# cd build/
open drum_machine.xcodeproj

Close vsCode

Xcode Navigator Toolbar

The Project navigator icon is highlighted at the upper left. This icon displays the project source files. Note that the Source Files folder has been expanded.

Click hw431_main.cpp to open it.

xcode5.png

The nine icons in the Navigator Toolbar display the following views.
The Heirarchical View displays classes and methods.
Click to navigate to the function.

xcode21.png

Viewing header and source files

You can easily view corresponding header files for the currently displayed source file by clicking the Related Items icon.

xcode33.png

You can view all source files in the project by clicking the Source Files icon.

xcode16.png

Build and Debug in Xcode \\

Click and hold the ALL_BUILD button and choose drum_machine.

xcode3.png

You can also access this from the Product menu.

xcode9.png

Click the Build and Run button

xcode27.png

When the compile finishes any program output will be shown in the right panel at the bottom of the window.
I enlarged the display panel by dragging the gray divider bar upwards.

xcode29.png

The drum_machine executable can be found in the Products folder.

xcode35.png

Breakpoints

Display hw431_main.cpp and set a breakpoint on line 31 by clicking just to the left of the 31.

xcode6.png

Run the program again and it will stop at line 34.
Breakpoint information is highlighted in green on the right.

xcode28.png

These are the the debugger commands that allow you to trace through your code line by line.

Step Into
If the line about to be execucted is function, step into that function.
Stop Over
If the line about to be execucted is function, step over it.
Step Out
If you are in a function and want to return to the caller step out.

Use the Step Into, Step Over, and Step Out commands either from the menu

xcode22.png

or from the debugger toolbar

xcode17.png

or the Shortcut keys: F6, F7, F8 (Shown above in the Debug menu picture).

Choose Step into

xcode18.png

When the debugger halts at the first line of CDrumMachine::make_track() you can examine the values of variables in the left panel of at the bottom of the screen. Here I've right clicked the the note variable and am about to change the display from char ('%') to Decimal (37).

xcode23.png

Hovering the mouse over the variable in the source code will display its value at that point in the program.

xcode25.png

You'll recall we got here from main() where the two variables pasted into dm.make_track() were 37 and {"1000", "1000", "1000", "1000"}.

xcode19.png

Step Over three more times until you stop at the closing brace of DrumMachine::make_track().
Expand the variables and you can see the the vDrumTracks vector for the first row of the drum machine has been setup with the drum note number, the beat pattern for the first measure, and the duration of each beat.

xcode24.png

You can display either the Variables or Output pane by clicking these icons at the lower right. You can resize them proportionately by dragging the vertical divider separating them.

xcode26.png

Stack trace

You can view a stack trace that displays the trail of function calls or "How did I get here?"

xcode20.png

Click and hold the Stack Frame icon and the call tree will appear. You can click any one of these functions examine and how variables were changed as you arrived here.

xcode10.png

Ending a debug session

Click the Stop button.

xcode36.png

Or click the Deactivate breakpoints icon and then the Continue program execution icon.

xcode17.png

Xcode is a very deep and comprehensive program. We've only scratched the surface but now have a valuable tool that can step through your code and and help you spot and fix errors.

My output
This is the output I used to create the mp3 file at the beginning of this page. One cycle through the 16 columns of the drum machine.

# mp3 tempo was 75 bpm
0       99      36      100
500     99      42      100
500     99      43      100
500     99      46      100
500     99      37      100
749     89      37      0
749     89      46      0
749     89      42      0
749     89      43      0
750     99      50      100
750     99      38      100
1000    99      36      100
1249    89      36      0
1250    99      37      100
1499    89      37      0
1500    99      46      100
1500    99      38      100
1500    99      42      100
1749    89      46      0
1749    89      38      0
1749    89      42      0
1750    99      50      100
2000    99      36      100
2249    89      36      0
2250    99      37      100
2499    89      37      0
2500    99      46      100
2500    99      50      100
2500    99      42      100
2749    89      50      0
2749    89      42      0
2749    89      46      0
2750    99      38      100
3000    99      36      100
3249    89      36      0
3250    99      37      100
3499    89      37      0
3500    99      42      100
3500    99      50      100
3500    99      39      100
3500    99      38      100
3500    99      46      100
3749    89      38      0
3749    89      39      0
3749    89      50      0
3750    99      37      100
3750    99      42      100
3750    99      46      100
4000    99      36      100
4249    89      36      0
4500    99      42      100
4500    99      46      100
4500    99      43      100
4500    99      37      100
4749    89      37      0
4749    89      43      0
4749    89      42      0
4749    89      46      0
4750    99      38      100
4750    99      50      100
5000    99      36      100
5249    89      36      0
5250    99      37      100
5499    89      37      0
5500    99      38      100
5500    99      42      100
5500    99      46      100
5749    89      42      0
5749    89      46      0
5749    89      38      0
5750    99      50      100
6000    99      36      100
6249    89      36      0
6250    99      37      100
6499    89      37      0
6500    99      50      100
6500    99      42      100
6500    99      46      100
6749    89      46      0
6749    89      50      0
6749    89      42      0
6750    99      38      100
7000    99      36      100
7249    89      36      0
7250    99      37      100
7499    89      37      0
7500    99      46      100
7500    99      50      100
7500    99      38      100
7500    99      42      100
7500    99      39      100
7749    89      39      0
7749    89      38      0
7749    89      50      0
7750    99      46      100
7750    99      42      100
7750    99      37      100
8000    99      36      100
8249    89      36      0
8500    99      46      100
8500    99      43      100
8500    99      42      100
8500    99      37      100
8749    89      43      0
8749    89      37      0
8749    89      42      0
8749    89      46      0
8750    99      50      100
8750    99      38      100
9000    99      36      100
9249    89      36      0
9250    99      37      100
9499    89      37      0
9500    99      46      100
9500    99      38      100
9500    99      42      100
9749    89      42      0
9749    89      38      0
9749    89      46      0
9750    99      50      100
10000   99      36      100
10249   89      36      0
10250   99      37      100
10499   89      37      0
10500   99      46      100
10500   99      42      100
10500   99      50      100
10749   89      46      0
10749   89      50      0
10749   89      42      0
10750   99      38      100
11000   99      36      100
11249   89      36      0
11250   99      37      100
11499   89      37      0
11500   99      39      100
11500   99      38      100
11500   99      50      100
11500   99      46      100
11500   99      42      100
11749   89      50      0
11749   89      39      0
11749   89      38      0
11750   99      46      100
11750   99      37      100
11750   99      42      100
12000   99      36      100
12249   89      36      0
12500   99      37      100
12500   99      42      100
12500   99      46      100
12500   99      43      100
12749   89      43      0
12749   89      46      0
12749   89      37      0
12749   89      42      0
12750   99      50      100
12750   99      38      100
13000   99      36      100
13249   89      36      0
13250   99      37      100
13499   89      37      0
13500   99      46      100
13500   99      42      100
13500   99      38      100
13749   89      38      0
13749   89      42      0
13749   89      46      0
13750   99      50      100
14000   99      36      100
14249   89      36      0
14250   99      37      100
14499   89      37      0
14500   99      46      100
14500   99      42      100
14500   99      50      100
14749   89      46      0
14749   89      42      0
14749   89      50      0
14750   99      38      100
15000   99      36      100
15249   89      36      0
15250   99      37      100
15499   89      37      0
15500   99      42      100
15500   99      50      100
15500   99      46      100
15500   99      38      100
15500   99      39      100
15749   89      38      0
15749   89      39      0
15749   89      50      0
15750   99      46      100
15750   99      42      100
15750   99      37      100

Submission

Feel free to email jellinge@carleton.edu on any part of the homework that is unclear to you. Chances are if you have questions other students do too. I will answer those questions by email to everyone in the class. The original sender will remain anonymous. I have tried to provide clues to the homework in the web pages, reading assignments, and labs. Sometimes what seems obvious to me is not obvious to students just learning C++.

Create a folder named hwNN_LastnameFirstname1_LastnameFirstname2.
Substitute your name and your partner's name for LastnameFirstname1_LastnameFirstname2.

Remember

  • Boilerplate header at top of every file.
  • Make sure your program compiles before submitting.
  • Programs that compile and produce partially correct output will be graded.
  • You can send notes to me in your homework files by enclosing them in block comments.
  • Programs that do not compile get an automatic F (59%).
  • Each partner must submit identical homework folders to the course Hand-in folder.
  • If only one partner submits the homework send me an email explaining why.
  • Empty your build or build-debug folders using the command emptyBuildFolder.sh
  • Only include .h, .cpp, Makefiles, CMakeLists.txt
  • Do not include these folders/files
    .git
    .vscode
  • Double check for the above two folders using this command

    ls -a hwNN_LastnameFirstname1_LastnameFirstname2
    # if either .git or .vscode exist in the folder you're submitting remove them with
    # rm -fR .git
    # rm -fR .vscode
    
$HOME312/common
├── hw332_CMidiPacket.cpp
├── hw332_CMidiPacket.h
├── hw423_CMidiTrack.cpp
├── hw423_CMidiTrack.h
├── hw421_CDelayMs.cpp
├── hw421_CDelayMs.h
├── hw422_CAppleMidiSynth.cpp
└── hw422_CAppleMidiSynth.h

$HOME312/cs312/hw43/hw431_drumMachine
├── CMakeLists.txt
├── build
├── hw431_CDrumMachine.cpp
├── hw431_CDrumMachineh.h
├── hw431_CDrumTrack.cpp
├── hw431_CDrumTrack.h
└── hw431_main.cpp

Author: John Ellinger

Created: 2020-02-01 Sat 15:48

Validate