Skip to content

Commit 2ca1e0c

Browse files
committed
Added Tonic to dependencies to do some music theory stuff in pitch correction
1 parent c642f9b commit 2ca1e0c

File tree

4 files changed

+52
-17
lines changed

4 files changed

+52
-17
lines changed

Package.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ let package = Package(
1111
.package(url: "https://github.com/AudioKit/KissFFT", from: "1.0.0"),
1212
.package(url: "https://github.com/AudioKit/AudioKit", from: "5.6.0"),
1313
.package(url: "https://github.com/AudioKit/AudioKitEX", from: "5.5.0"),
14+
.package(url: "https://github.com/AudioKit/Tonic", from: "2.0.0"),
1415
],
1516
targets: [
1617
.target(name: "Soundpipe",
@@ -22,9 +23,9 @@ let package = Package(
2223
.headerSearchPath("modules"),
2324
.headerSearchPath("external"),
2425
]),
25-
.target(name: "SoundpipeAudioKit", dependencies: ["AudioKit", "AudioKitEX", "CSoundpipeAudioKit"]),
26+
.target(name: "SoundpipeAudioKit", dependencies: ["AudioKit", "AudioKitEX", "CSoundpipeAudioKit", "Tonic"]),
2627
.target(name: "CSoundpipeAudioKit", dependencies: ["AudioKit", "AudioKitEX", "Soundpipe"]),
27-
.testTarget(name: "SoundpipeAudioKitTests", dependencies: ["SoundpipeAudioKit"], resources: [.copy("TestResources/")]),
28+
.testTarget(name: "SoundpipeAudioKitTests", dependencies: ["SoundpipeAudioKit", "Tonic"], resources: [.copy("TestResources/")]),
2829
.testTarget(name: "CSoundpipeAudioKitTests", dependencies: ["CSoundpipeAudioKit"]),
2930
],
3031
cxxLanguageStandard: .cxx14

Sources/CSoundpipeAudioKit/Effects/PitchCorrectDSP.mm

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,8 @@ void init(int channelCount, double sampleRate) override {
4545
pitchcorrect_init(sp, pitchcorrect_r);
4646

4747
// Default chromatic scale from A1 (55Hz) to A6 (1760Hz)
48-
float defaultScale[73] = {
49-
55.00, 58.27, 61.74, 65.41, 69.30, 73.42, 77.78, 82.41, 87.31, 92.50, 98.00, 103.83, // A1 to G#2
50-
110.00, 116.54, 123.47, 130.81, 138.59, 146.83, 155.56, 164.81, 174.61, 185.00, 196.00, 207.65, // A2 to G#3
51-
220.00, 233.08, 246.94, 261.63, 277.18, 293.66, 311.13, 329.63, 349.23, 369.99, 392.00, 415.30, // A3 to G#4
52-
440.00, 466.16, 493.88, 523.25, 554.37, 587.33, 622.25, 659.26, 698.46, 739.99, 783.99, 830.61, // A4 to G#5
53-
880.00, 932.33, 987.77, 1046.50, 1108.73, 1174.66, 1244.51, 1318.51, 1396.91, 1479.98, 1567.98, 1661.22, // A5 to G#6
54-
1760.00 // A6
55-
};
56-
setWavetable(defaultScale, 73, 0);
48+
float defaultScale[1] = {440.00};
49+
setWavetable(defaultScale, 1, 0);
5750
}
5851

5952
void deinit() override {

Sources/SoundpipeAudioKit/Effects/PitchCorrect.swift

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@ import AudioKit
44
import AudioKitEX
55
import AVFoundation
66
import CAudioKitEX
7+
import Tonic
78

89
/// Pitch correction
910
public class PitchCorrect: Node {
1011
let input: Node
11-
12+
13+
var key: Key
14+
1215
/// Connected nodes
1316
public var connections: [Node] { [input] }
1417

@@ -49,25 +52,56 @@ public class PitchCorrect: Node {
4952
///
5053
/// - Parameters:
5154
/// - input: Input node to process
55+
/// - key: Key to tune to
56+
/// - scale: Scale to use (default: major)
5257
/// - speed: Speed of pitch correction (0-1)
5358
/// - amount: Amount of pitch correction (0-1)
5459
///
5560
public init(
5661
_ input: Node,
62+
key: Key = .C,
5763
speed: AUValue = speedDef.defaultValue,
5864
amount: AUValue = amountDef.defaultValue
5965
) {
6066
self.input = input
61-
67+
self.key = key
68+
69+
updateScaleFrequencies()
70+
6271
setupParameters()
6372

6473
self.speed = speed
6574
self.amount = amount
75+
76+
updateScaleFrequencies()
6677
}
6778

68-
/// Set the scale frequencies for pitch correction
69-
/// - Parameter frequencies: Array of frequencies in Hz
70-
public func setScaleFrequencies(_ frequencies: [Float]) {
79+
/// Update the scale frequencies based on current key and scale
80+
private func updateScaleFrequencies() {
81+
var frequencies: [Float] = []
82+
83+
// Generate notes for octaves 0 through 7
84+
for octave in 0...7 {
85+
for noteClass in key.noteSet.noteClassSet.array {
86+
let noteWithOctave = Note(noteClass.letter, accidental: noteClass.accidental, octave: octave)
87+
print(noteClass)
88+
frequencies.append(Float(noteWithOctave.pitch.frequency))
89+
}
90+
}
91+
92+
// Sort frequencies in ascending order
93+
frequencies.sort()
94+
print(frequencies)
95+
print(frequencies.count)
96+
97+
// Set the frequencies in the DSP
7198
au.setWavetable(frequencies)
7299
}
100+
101+
}
102+
103+
extension Pitch {
104+
var frequency: Double {
105+
return Double(UInt8(midiNoteNumber).midiNoteToFrequency())
106+
}
73107
}

Tests/SoundpipeAudioKitTests/Effects Tests/PitchCorrectTests.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import AudioKit
44
import SoundpipeAudioKit
55
import XCTest
66
import AVFoundation
7+
import Tonic
78

89
class PitchCorrectTests: XCTestCase {
910
func testPitchCorrect() {
@@ -15,7 +16,7 @@ class PitchCorrectTests: XCTestCase {
1516
oscillator.amplitude = 0.5
1617

1718
// Create pitch correction
18-
let pitchCorrect = PitchCorrect(oscillator, speed: 1.0, amount: 1.0)
19+
let pitchCorrect = PitchCorrect(oscillator, key: .A, speed: 1.0, amount: 1.0)
1920

2021
engine.output = pitchCorrect
2122

@@ -27,8 +28,14 @@ class PitchCorrectTests: XCTestCase {
2728
// Ramp frequency from 110 to 880 over 10 seconds
2829
oscillator.$frequency.ramp(to: 440, duration: 5.0)
2930

31+
// pitchCorrect.setScaleFrequencies([220,245,350,395])
32+
// pitchCorrect.setValidNotes(root: .C, scale: .major)
33+
// pitchCorrect.setValidNotes(.C, .Dsharp, .E)
34+
35+
3036
audio.append(engine.render(duration: 5.0))
3137

3238
testMD5(audio)
39+
audio.audition()
3340
}
3441
}

0 commit comments

Comments
 (0)