cienicera / cairo-wave

An implementation of the WAVE file format in Cairo
MIT License
6 stars 11 forks source link

Implement custom notes waveform #12

Open tekkac opened 3 months ago

tekkac commented 3 months ago

Contributing

Description

Implement custom notes generated from Koji

Notes should respect the Koji format and include modes

Additional Information

[Low Difficult - Cairo - Medium Priority]

Acceptance Criteria

estherbreath commented 3 months ago

Can I handle this?

caseywescott commented 3 months ago

Hey @tekkac !

I'm stoked about this feature and having Cairo-Wave and Koji integrate with each other! Esther asked some questions about Koji and wanted to help identify the right plan of attack for this feature as you envision it. Apologies if I'm late to the discussion...

Esther had shown me her code with the following pattern of a Note struct -> Music struct/span that then is fed into a Notes2Samples sample-player/wave-generator.

Looking at the struct Esther has been working on:

[derive(Drop, Copy, Serde)]

struct Note { frequency_hz: u32, duration_ms: u32, note_type: NoteType, }

This Note struct is a great abstraction that is well suited for synthesis but handles duration_ms differently from Koji's Midi approach of NoteOn/NoteOff pairs. Adopting Koji's MidiTrait for solving what you want to accomplish with the Note struct is awesome but more difficult than getting the basic feature going - Which is to enable cairo-wave to leverage the note/mode/harmonization operations of Koji...Would it make more sense to first integrate the PitchClass -> Frequency - > Note functionality? I'm thinking of this code from Koji:

let a_note = PitchClass { note: 9, octave: 4, }; // a above middle c let midikeynum = a_note.keynum; // keynum = 69 (the a above middle) let freq = pc_to_freq(midikeynum);

// pseudocode for pc_to_freq fn pc_to_freq(pc: PitchClass) -> u32 { let keynum = pc_to_keynum(pc); //need to make * cairo style let mut freq = 440 (2 ** ((keynum - 69) / 12)) freq }

keynum_to_freq's output would then be fed into Note structs which would then be synthesized with cairo-wave.

Does that seem like a decent way to start? Let me know what you envision as that will help me steer Esther in the good direction. Cheers

tekkac commented 3 months ago

@caseywescott thanks for the recap! I think your approach is the way to go. The Note struct above was a quick hack I developped for a PoC. The idea of this issue is exactly to integrate the Koji way of doing. I wasn't sure if PitchClass was they way to go so you pitched in at the right moment. So they plan might be to create a method or a impl of Into to convert a PitchClass into Samples or WavFile if the sample_rate is known. @estherbreath hopefully this clears things out a bit for you?

estherbreath commented 3 months ago

Thank you. This helps a lot

On Thu, Mar 21, 2024 at 6:57 PM Trunks @ Carbonable < @.***> wrote:

@caseywescott https://github.com/caseywescott thanks for the recap! I think your approach is the way to go. The Note struct above was a quick hack I developped for a PoC. The idea of this issue is exactly to integrate the Koji way of doing. I wasn't sure if PitchClass was they way to go so you pitched in at the right moment. So they plan might be to create a method or a impl of Into to convert a PitchClass into Samples or WavFile if the sample_rate is known. @estherbreath https://github.com/estherbreath hopefully this clears things out a bit for you?

— Reply to this email directly, view it on GitHub https://github.com/cienicera/cairo-wave/issues/12#issuecomment-2013183207, or unsubscribe https://github.com/notifications/unsubscribe-auth/AZTTUJ7HEQQVOQTH3X4NH7TYZMNSHAVCNFSM6AAAAABE2UQZOGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDAMJTGE4DGMRQG4 . You are receiving this because you were mentioned.Message ID: @.***>

caseywescott commented 3 months ago

Hey @estherbreath and @tekkac .

I'm gonna merge this to pitch.cairo so that PitchClassTrait can convert PitchClasses/midikeynums into frequencies Here is the code. Currently, the tests don't print out the decimal point values but the integer values are clean and ensure frequencies will be in tune within 1 hz which is good enough to hear some music (I do want higher precision so I might ping you @tekkac and Raph on that later).

So @estherbreath you can get the frequencies for your Note struct this way:

let a_note = PitchClass { note: 9, octave: 4, }; // A above middle C let freq = a_note.freq(); // 440hz

// or from a midikeynum: let keynum 69; // A-440, the A above middle C let freq2 = keynum_to_pc(keynum).freq().

Let me know if you have any questions or feedback!

caseywescott commented 3 months ago

Cool I merged that with the main branch so you are all set! Hit me up with any questions

estherbreath commented 3 months ago

Very well noted

estherbreath commented 3 months ago

I cloned the repo and tried to run scarb build on it. It showed me the errors below:

cairo wave error

tekkac commented 3 months ago

I think you need scarb v2.6.3 because of the latest syntax features

estherbreath commented 3 months ago

It's resolved. Thanks

estherbreath commented 3 months ago

I've sent a PR