Skip to content

Commit 4b1ee10

Browse files
committed
Clean up a little
1 parent a1ec4a7 commit 4b1ee10

File tree

13 files changed

+465
-291
lines changed

13 files changed

+465
-291
lines changed

app/src/nativeMain/kotlin/Main.kt

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,44 +16,44 @@ import platform.posix.sleep
1616
fun main() {
1717
val gOff = MidiMessageNoteOff(
1818
time = 10000,
19-
channel = 5,
19+
channel = 6,
2020
key = 32,
2121
next = null
2222
)
2323

2424
val g = MidiMessageNoteOn(
2525
time = 2500,
26-
channel = 5,
26+
channel = 6,
2727
key = 43,
2828
velocity = 80,
2929
next = gOff
3030
)
3131

3232
val eOff = MidiMessageNoteOff(
3333
time = 2000,
34-
channel = 7,
34+
channel = 3,
3535
key = 40,
3636
next = g
3737
)
3838

3939
val e = MidiMessageNoteOn(
4040
time = 1_000,
41-
channel = 7,
41+
channel = 3,
4242
key = 40,
4343
velocity = 80,
4444
next = eOff
4545
)
4646

4747
val cOff = MidiMessageNoteOff(
4848
time = 100,
49-
channel = 1,
49+
channel = 0,
5050
key = 36,
5151
next = e
5252
)
5353

5454
val c = MidiMessageNoteOn(
5555
time = 0,
56-
channel = 1,
56+
channel = 0,
5757
key = 36,
5858
velocity = 80,
5959
next = cOff
@@ -64,11 +64,8 @@ fun main() {
6464

6565
val soundFontPath = Path("D:\\src\\MidiWavConverter\\Example\\florestan-subset.sf2")
6666

67-
println("1")
6867
generator.setSoundFont(soundFontPath.toString())
69-
println("2")
7068
val midiBytes = generator.generate(c)
71-
println("3")
7269
val numSamples = midiBytes.size.toUInt() / sizeOf<FloatVar>().toUInt()
7370
val wavFileHeader = WavFileHeader.write(44100u, numSamples, 2u)
7471

core/build.gradle.kts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
2+
13
plugins {
24
alias(libs.plugins.kotlinMultiplatform)
35
id("maven-publish")
@@ -23,7 +25,13 @@ kotlin {
2325
}
2426
}
2527

28+
@OptIn(ExperimentalKotlinGradlePluginApi::class)
29+
compilerOptions {
30+
freeCompilerArgs.add("-Xexpect-actual-classes")
31+
}
32+
2633
sourceSets {
34+
2735
commonMain.dependencies {
2836
implementation(libs.coroutines.core)
2937
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package pl.lemanski.pandamidi.soundFont
2+
3+
/**
4+
* This class represents a channel on a soundfont.
5+
*/
6+
interface Channel {
7+
/**
8+
* The channel number
9+
*/
10+
11+
val number: Int
12+
13+
/**
14+
* Set preset index >= 0 and < [preset count]
15+
*/
16+
fun setPresetIndex(presetIndex: Int)
17+
18+
/**
19+
* Set preset number (alternative to presetIndex)
20+
*/
21+
fun setPresetNumber(presetNumber: Int, isMidiDrums: Boolean)
22+
23+
/**
24+
* Set instrument bank number (alternative to presetIndex)
25+
*/
26+
fun setBank(bank: Int)
27+
28+
/**
29+
* Set instrument bank and preset number
30+
*/
31+
fun setBankPreset(bank: Int, presetNumber: Int)
32+
33+
/**
34+
* Set stereo panning value from 0.0 (left) to 1.0 (right) (default 0.5 center)
35+
*/
36+
fun setPan(pan: Float)
37+
38+
/**
39+
* Set linear volume scale factor (default 1.0 full)
40+
*/
41+
fun setVolume(volume: Float)
42+
43+
/**
44+
* Set pitch wheel position 0 to 16383 (default 8192 unpitched)
45+
*/
46+
fun setPitchWheel(pitchWheel: Int)
47+
48+
/**
49+
* Set range of the pitch wheel in semitones (default 2.0, total +/- 2 semitones)
50+
*/
51+
fun setPitchRange(pitchRange: Float)
52+
53+
/**
54+
* Set tuning of all playing voices in semitones (default 0.0, standard (A440) tuning)
55+
*/
56+
fun setTuning(tuning: Float)
57+
58+
59+
/**
60+
* Start playing a note
61+
*/
62+
fun noteOn(key: Int, velocity: Float)
63+
64+
/**
65+
* Stop playing a note
66+
*/
67+
fun noteOff(key: Int)
68+
69+
/**
70+
* Stop playing all notes (end with sustain and release)
71+
*/
72+
fun noteOffAll()
73+
74+
/**
75+
* Stop playing all notes (end immediately)
76+
*/
77+
fun soundsOffAll()
78+
79+
80+
/**
81+
* Get current preset index set on the channel
82+
*/
83+
fun getPresetIndex(): Int
84+
85+
/**
86+
* Get current instrument bank set on the channel
87+
*/
88+
fun getPresetBank(): Int
89+
90+
/**
91+
* Get current preset number set on the channel
92+
*/
93+
fun getPresetNumber(): Int
94+
95+
/**
96+
* Get current stereo panning value from 0.0 (left) to 1.0 (right)
97+
*/
98+
fun getPan(): Float
99+
100+
/**
101+
* Get current linear volume scale factor
102+
*/
103+
fun getVolume(): Float
104+
105+
/**
106+
* Get current pitch wheel position
107+
*/
108+
fun getPitchWheel(): Int
109+
110+
/**
111+
* Get current range of the pitch wheel in semitones
112+
*/
113+
fun getPitchRange(): Float
114+
115+
/**
116+
* Get current tuning of all playing voices in semitones
117+
*/
118+
fun getTuning(): Float
119+
}

core/src/commonMain/kotlin/pl/lemanski/pandamidi/soundFont/SoundFont.kt

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,7 @@
11
package pl.lemanski.pandamidi.soundFont
22

33
interface SoundFont {
4-
/**
5-
* Copy a tsf instance from an existing one, use tsf_close to close it as well.
6-
* All copied tsf instances and their original instance are linked, and share the underlying soundfont.
7-
* This allows loading a soundfont only once, but using it for multiple independent playbacks.
8-
* (This function isn't thread-safe without locking.)
9-
*/
10-
fun copy(): SoundFont
11-
12-
/**
13-
* Free the memory related to this tsf instance
14-
*/
15-
fun close()
4+
val channels: List<Channel>
165

176
/**
187
* Stop all playing notes immediately and reset all channel parameters
@@ -114,7 +103,8 @@ interface SoundFont {
114103
fun setBankPreset(channel: Int, bank: Int, presetNumber: Int)
115104

116105
/**
117-
* Render output samples
106+
* Render output samples in F32 format
107+
* @param isMixing: if false clear the buffer first, otherwise mix into existing data
118108
*/
119109
fun renderFloat(samples: Int, isMixing: Boolean): FloatArray
120110

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,5 @@
11
package pl.lemanski.pandamidi.soundFont
22

3-
import pl.lemanski.pandamidi.soundFont.internal.SoundFontDelegate
3+
expect fun soundFont(path: String): SoundFont
44

5-
fun soundFont(path: String): SoundFont {
6-
loadFromFile(path)
7-
return object : SoundFont by SoundFontDelegate() { }
8-
}
9-
10-
fun soundFont(memory: ByteArray): SoundFont {
11-
loadFromMemory(memory)
12-
return object : SoundFont by SoundFontDelegate() { }
13-
}
14-
15-
internal expect fun loadFromFile(path: String)
16-
17-
internal expect fun loadFromMemory(memory: ByteArray)
5+
expect fun soundFont(memory: ByteArray): SoundFont
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package pl.lemanski.pandamidi.soundFont.internal
2+
3+
import pl.lemanski.pandamidi.soundFont.Channel
4+
5+
internal expect class ChannelDelegate : Channel

core/src/commonMain/kotlin/pl/lemanski/pandamidi/soundFont/internal/SoundFontDelegate.kt

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,41 +2,4 @@ package pl.lemanski.pandamidi.soundFont.internal
22

33
import pl.lemanski.pandamidi.soundFont.SoundFont
44

5-
internal open class SoundFontDelegate : SoundFont {
6-
7-
override fun copy(): SoundFont = SoundFontDelegate() // TODO implement
8-
9-
override fun close() = close(this)
10-
11-
override fun reset() = reset(this)
12-
13-
override fun getPresetIndex(bank: Int, presetNumber: Int): Int = getPresetIndex(this, bank, presetNumber)
14-
15-
override fun getPresetsCount(): Int = getPresetsCount(this)
16-
17-
override fun getPresetName(presetIndex: Int): String = getPresetName(this, presetIndex)
18-
19-
override fun bankGetPresetName(bank: Int, presetNumber: Int): String = bankGetPresetName(this, bank, presetNumber)
20-
21-
override fun setOutput(outputMode: SoundFont.OutputMode, sampleRate: Int, globalGainDb: Float) = setOutput(this, outputMode, sampleRate, globalGainDb)
22-
23-
override fun setVolume(globalGain: Float) = setVolume(this, globalGain)
24-
25-
override fun setMaxVoices(maxVoices: Int) = setMaxVoices(this, maxVoices)
26-
27-
override fun noteOn(presetIndex: Int, key: Int, velocity: Float) = noteOn(this, presetIndex, key, velocity)
28-
29-
override fun bankNoteOn(bank: Int, presetNumber: Int, key: Int, velocity: Float) = bankNoteOn(this, bank, presetNumber, key, velocity)
30-
31-
override fun noteOff(presetIndex: Int, key: Int) = noteOff(this, presetIndex, key)
32-
33-
override fun bankNoteOff(bank: Int, presetNumber: Int, key: Int) = bankNoteOff(this, bank, presetNumber, key)
34-
35-
override fun noteOffAll() = noteOffAll(this)
36-
37-
override fun activeVoiceCount(): Int = activeVoiceCount(this)
38-
39-
override fun setBankPreset(channel: Int, bank: Int, presetNumber: Int) = setBankPresetNumber(this, channel, bank, presetNumber)
40-
41-
override fun renderFloat(samples: Int, isMixing: Boolean): FloatArray = renderFloat(this, samples, isMixing)
42-
}
5+
internal expect class SoundFontDelegate : SoundFont

core/src/commonMain/kotlin/pl/lemanski/pandamidi/soundFont/internal/SoundFontExtInternal.kt

Lines changed: 0 additions & 37 deletions
This file was deleted.
Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,11 @@
11
package pl.lemanski.pandamidi.soundFont
22

3-
import kotlinx.cinterop.ExperimentalForeignApi
4-
import kotlinx.cinterop.refTo
5-
import pl.lemanski.pandamidi.soundFont.internal.SoundFontHolder
6-
import tinySoundFont.tsf_load_filename
7-
import tinySoundFont.tsf_load_memory
3+
import pl.lemanski.pandamidi.soundFont.internal.SoundFontDelegate
84

9-
@OptIn(ExperimentalForeignApi::class)
10-
internal actual fun loadFromFile(path: String) {
11-
SoundFontHolder.tsf = tsf_load_filename(path) ?: throw IllegalStateException("SoundFont not loaded")
12-
}
13-
14-
@OptIn(ExperimentalForeignApi::class)
15-
internal actual fun loadFromMemory(memory: ByteArray) {
16-
SoundFontHolder.tsf = tsf_load_memory(memory.refTo(0), memory.size) ?: throw IllegalStateException("SoundFont not loaded")
5+
actual fun soundFont(path: String): SoundFont {
6+
return SoundFontDelegate(path)
177
}
188

9+
actual fun soundFont(memory: ByteArray): SoundFont {
10+
return SoundFontDelegate(memory)
11+
}

0 commit comments

Comments
 (0)