234 lines
5.8 KiB
Markdown
234 lines
5.8 KiB
Markdown
[](https://gitea.hub.saturnux.com/sylvain/BitBuzzer)
|
|
[](https://en.cppreference.com/w/cpp/23)
|
|
[](https://cmake.org/)
|
|
[](https://creativecommons.org/publicdomain/zero/1.0/)
|
|
[]()
|
|
|
|
# 🎵 BitBuzzer - Musical Notes Library
|
|
|
|
A simple and lightweight C++23 library for defining musical notes with their frequencies and durations.
|
|
|
|
## 📋 Description
|
|
|
|
This library provides:
|
|
- 📦 A simple header-only interface for musical notes
|
|
- 🎶 A comprehensive set of musical notes from B0 (31 Hz) to DS8 (4978 Hz)
|
|
- ⏱️ Support for note durations using `std::chrono::milliseconds`
|
|
- ✨ A `Note` structure to represent a musical note with its frequency and duration
|
|
- 🎹 Predefined constants for all notes from B0 (31 Hz) to DS8 (4978 Hz)
|
|
- ⏱️ Duration support with `std::chrono::milliseconds`
|
|
|
|
## 🎼 Available Notes
|
|
|
|
The library defines all notes of the Western musical system across 8 octaves:
|
|
|
|
### 🎹 Octave 0-1
|
|
- **B0** (31 Hz) to **B1** (62 Hz)
|
|
|
|
### 🎹 Octave 2
|
|
- **C2** (65 Hz) to **B2** (123 Hz)
|
|
|
|
### 🎹 Octave 3
|
|
- **C3** (131 Hz) to **B3** (247 Hz)
|
|
|
|
### 🎹 Octave 4 (Middle Octave)
|
|
- **C4** (262 Hz) to **B4** (494 Hz)
|
|
- **A4** = 440 Hz (Concert pitch reference)
|
|
|
|
### 🎹 Octave 5
|
|
- **C5** (523 Hz) to **B5** (988 Hz)
|
|
|
|
### 🎹 Octave 6
|
|
- **C6** (1047 Hz) to **B6** (1976 Hz)
|
|
|
|
### 🎹 Octave 7
|
|
- **C7** (2093 Hz) to **B7** (3951 Hz)
|
|
|
|
### 🎹 Octave 8
|
|
- **C8** (4186 Hz) to **DS8** (4978 Hz)
|
|
|
|
### 🔇 Special Notes
|
|
- **silent** (0 Hz) - For rests/pauses
|
|
|
|
### 📝 Notation
|
|
- Natural notes: C, D, E, F, G, A, B
|
|
- Sharps (♯): CS, DS, FS, GS, AS (suffix 'S' for Sharp)
|
|
- Flats (♭): DB3, EB3 (suffix 'B' for Flat) - Enharmonic equivalents available for some notes
|
|
|
|
## 🏗️ Note Structure
|
|
|
|
```cpp
|
|
struct Note
|
|
{
|
|
uint16_t frequency; // Frequency in Hz
|
|
std::chrono::milliseconds duration; // Note duration
|
|
};
|
|
```
|
|
|
|
### 🔧 Constructors
|
|
|
|
```cpp
|
|
// With std::chrono::milliseconds
|
|
Note(uint16_t freq, std::chrono::milliseconds dur);
|
|
|
|
// With uint32_t (automatically converted to milliseconds)
|
|
Note(uint16_t freq, uint32_t dur);
|
|
```
|
|
|
|
## 📦 Project Integration: Direct Inclusion
|
|
|
|
1. Copy the `pitches` folder to the root of your project or into a subfolder like `external/` or `libs/`
|
|
|
|
2. In your `CMakeLists.txt`, add the path to includes:
|
|
|
|
```cmake
|
|
# Add the pitches folder to includes
|
|
target_include_directories(your_project PRIVATE
|
|
${CMAKE_CURRENT_SOURCE_DIR}/pitches
|
|
)
|
|
```
|
|
|
|
3. Include the header in your code:
|
|
|
|
```cpp
|
|
#include <pitches/pitches.h>
|
|
```
|
|
|
|
## 💡 Usage Examples
|
|
|
|
### 🎯 Example 1: Create a Simple Note
|
|
|
|
```cpp
|
|
#include <pitches/pitches.h>
|
|
|
|
int main()
|
|
{
|
|
// A4 note (440 Hz) for 500ms
|
|
pitches::Note note1(pitches::A4, 500);
|
|
|
|
// C5 note for 1 second
|
|
pitches::Note note2(pitches::C5, std::chrono::milliseconds(1000));
|
|
|
|
// 200ms rest/silence
|
|
pitches::Note pause(pitches::silent, 200);
|
|
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
### 🎶 Example 2: Simple Melody
|
|
|
|
```cpp
|
|
#include <pitches/pitches.h>
|
|
#include <vector>
|
|
|
|
std::vector<pitches::Note> createMelody()
|
|
{
|
|
using namespace pitches;
|
|
|
|
return {
|
|
Note(C4, 250), // Do
|
|
Note(D4, 250), // Re
|
|
Note(E4, 250), // Mi
|
|
Note(F4, 250), // Fa
|
|
Note(G4, 250), // Sol
|
|
Note(A4, 250), // La
|
|
Note(B4, 250), // Si
|
|
Note(C5, 500) // Do (higher octave)
|
|
};
|
|
}
|
|
```
|
|
|
|
### 🔊 Example 3: Note Playback Function
|
|
|
|
```cpp
|
|
#include <pitches/pitches.h>
|
|
#include <thread>
|
|
#include <iostream>
|
|
|
|
void playNote(const pitches::Note& note)
|
|
{
|
|
if (note.frequency == pitches::silent) {
|
|
std::cout << "Silence for " << note.duration.count() << "ms\n";
|
|
} else {
|
|
std::cout << "Playing frequency " << note.frequency
|
|
<< " Hz for " << note.duration.count() << "ms\n";
|
|
// Here: code to generate sound with the given frequency
|
|
}
|
|
|
|
std::this_thread::sleep_for(note.duration);
|
|
}
|
|
|
|
int main()
|
|
{
|
|
using namespace pitches;
|
|
|
|
std::vector<Note> melody = {
|
|
Note(E5, 200),
|
|
Note(E5, 200),
|
|
Note(silent, 200),
|
|
Note(E5, 200),
|
|
Note(silent, 200),
|
|
Note(C5, 200),
|
|
Note(E5, 400),
|
|
Note(G5, 400)
|
|
};
|
|
|
|
for (const auto& note : melody) {
|
|
playNote(note);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
### 🔌 Example 4: With Hardware Buzzer (Arduino-style)
|
|
|
|
```cpp
|
|
#include <pitches/pitches.h>
|
|
|
|
class Buzzer
|
|
{
|
|
public:
|
|
void play(const pitches::Note& note)
|
|
{
|
|
if (note.frequency > 0) {
|
|
tone(buzzerPin, note.frequency);
|
|
delay(note.duration.count());
|
|
noTone(buzzerPin);
|
|
} else {
|
|
delay(note.duration.count());
|
|
}
|
|
}
|
|
|
|
private:
|
|
int buzzerPin = 9; // Buzzer pin
|
|
};
|
|
```
|
|
|
|
## ⚙️ Requirements
|
|
|
|
- **C++ Standard**: C++23 (or C++17 minimum for `std::chrono`)
|
|
- **CMake**: Version 3.23 or higher
|
|
- **Compiler**: C++23 compatible (GCC 11+, Clang 14+, MSVC 2022+)
|
|
|
|
## 🔍 Technical Notes
|
|
|
|
- ⚡ All constants are `constexpr` for compile-time evaluation
|
|
- 📊 Frequencies are stored as `uint16_t` (0-65535 Hz)
|
|
- 🎯 `Note` structure is `constexpr`-compatible for static melodies
|
|
- 📄 Header-only: no separate compilation needed
|
|
|
|
## 📜 License
|
|
|
|
This project is licensed under CC0 1.0 Universal (Public Domain Dedication).
|
|
|
|
To the extent possible under law, the author has waived all copyright and related or
|
|
neighboring rights to this work. You can copy, modify, distribute and perform the work,
|
|
even for commercial purposes, all without asking permission.
|
|
|
|
## 🤝 Contributing
|
|
|
|
Sylvain Schneider (mailto:s.schneider.fr54@gmail.com)
|
|
|