Skip to content

Commit

Permalink
Add example program to examples/
Browse files Browse the repository at this point in the history
  • Loading branch information
Holzhaus committed Jan 14, 2021
1 parent a010130 commit e8299b9
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,15 @@ jobs:
working-directory: build
env:
CTEST_PARALLEL_LEVEL: 2
- name: Build example application
run: |
mkdir build
cd build
cmake ${{ matrix.cmake_extras }} ..
cmake --build .
working-directory: examples
env:
CMAKE_PREFIX_PATH: ${{ matrix.install_dir }}
- name: Upload Build Artifact
uses: actions/upload-artifact@v2
with:
Expand Down
8 changes: 8 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.1.0)
project(KeyFinderBasicExample)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../cmake")

find_package(KeyFinder CONFIG REQUIRED)
add_executable(basic basic.cpp)
target_link_libraries(basic PRIVATE KeyFinder::keyfinder)
158 changes: 158 additions & 0 deletions examples/basic.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
#include <cstdint>
#include <cstdio>
#include <cstring>

#include <keyfinder/keyfinder.h>
#include <keyfinder/audiodata.h>

// WAVE header as described here:
// http://soundfile.sapp.org/doc/WaveFormat/
typedef struct WAVE_HEADER {
/* RIFF Chunk Descriptor */
uint8_t ChunkID[4];
uint32_t ChunkSize;
uint8_t Format[4];
/* "fmt" sub-chunk */
uint8_t SubChunk1ID[4];
uint32_t SubChunk1Size;
uint16_t AudioFormat;
uint16_t NumChannels;
uint32_t SampleRate;
uint32_t ByteRate;
uint16_t BlockAlign;
uint16_t BitsPerSample;
/* "data" sub-chunk */
uint8_t Subchunk2ID[4];
uint32_t Subchunk2Size;
} wave_header_t;

int main(int argc, char* argv[]) {
if (argc != 2) {
fprintf(stderr, "usage: %s WAVE_FILE\n", argv[0]);
return 1;
}

const char* filePath = argv[1];
FILE* file = fopen(filePath, "r");
if (file == nullptr) {
fprintf(stderr, "Failed to open WAVE file: %s\n", filePath);
return 2;
}

wave_header_t waveHeader;
size_t bytesRead = fread(&waveHeader, 1, sizeof(waveHeader), file);
if (bytesRead < sizeof(waveHeader)) {
fprintf(stderr, "Failed to read WAVE header.\n");
return 3;
}

const size_t sampleSize = waveHeader.BitsPerSample / 8;
const auto numSamples = static_cast<unsigned int>(waveHeader.Subchunk2Size / (waveHeader.NumChannels * sampleSize));

// Prepare the object for your audio stream
KeyFinder::AudioData a;
printf("Sample Rate: %d\n", waveHeader.SampleRate);
a.setFrameRate(waveHeader.SampleRate);
printf("Num Channels: %d\n", waveHeader.NumChannels);
a.setChannels(waveHeader.NumChannels);
printf("Num Samples: %u\n", numSamples);
a.addToSampleCount(numSamples);

// Copy audio into the object
int8_t* buffer = new int8_t[sampleSize];
int i = 0;
while (fread(buffer, sizeof(buffer[0]), sampleSize / (sizeof buffer[0]), file) == sampleSize) {
uint32_t sample = 0;
for(int i = 0; i < sampleSize; i++) {
sample |= buffer[i] << (i * 8);
}
a.setSample(i, sample);
i++;
}
delete[] buffer;
fclose(file);

// Run the analysis
KeyFinder::KeyFinder k;
KeyFinder::key_t key = k.keyOfAudio(a);
// And do something with the result
switch(key) {
case KeyFinder::A_MAJOR:
puts("A major\n");
break;
case KeyFinder::A_MINOR:
puts("A minor\n");
break;
case KeyFinder::B_FLAT_MAJOR:
puts("B flat major\n");
break;
case KeyFinder::B_FLAT_MINOR:
puts("B flat minor\n");
break;
case KeyFinder::B_MAJOR:
puts("B major\n");
break;
case KeyFinder::B_MINOR:
puts("B minor\n");
break;
case KeyFinder::C_MAJOR:
puts("C major\n");
break;
case KeyFinder::C_MINOR:
puts("C minor\n");
break;
case KeyFinder::D_FLAT_MAJOR:
puts("D flat major\n");
break;
case KeyFinder::D_FLAT_MINOR:
puts("D flat major\n");
break;
case KeyFinder::D_MAJOR:
puts("D major\n");
break;
case KeyFinder::D_MINOR:
puts("D minor\n");
break;
case KeyFinder::E_FLAT_MAJOR:
puts("E flat major\n");
break;
case KeyFinder::E_FLAT_MINOR:
puts("E flat minor\n");
break;
case KeyFinder::E_MAJOR:
puts("E major\n");
break;
case KeyFinder::E_MINOR:
puts("E minor\n");
break;
case KeyFinder::F_MAJOR:
puts("G major\n");
break;
case KeyFinder::F_MINOR:
puts("G minor\n");
break;
case KeyFinder::G_FLAT_MAJOR:
puts("G flat major\n");
break;
case KeyFinder::G_FLAT_MINOR:
puts("G flat minor\n");
break;
case KeyFinder::G_MAJOR:
puts("G major\n");
break;
case KeyFinder::G_MINOR:
puts("G minor\n");
break;
case KeyFinder::A_FLAT_MAJOR:
puts("A flat major\n");
break;
case KeyFinder::A_FLAT_MINOR:
puts("A flat minor\n");
break;
case KeyFinder::SILENCE:
puts("Silence\n");
break;
}

return 0;
}

0 comments on commit e8299b9

Please sign in to comment.