My Music Editor

Started by Hardcoal, May 24, 2021, 23:57:24

Previous topic - Next topic

Hardcoal

#105
I did not experiment with looping at all yet.
But im not trying to loop something from the middle of a sample.
I will reach loop testing only in the future.
Im still working on the basic track editing process.
Soon ill finish with it and release a demo.
Than ill move on to looping tests.
And see the related issues you mentioned
And see what to do.

I think im back on track..
Most of the things seem to work,
And im making rather complicated things.
It's interesting because im not planning to do what's been done before, im going to try new stuff.
Like sample prefabs, which means when you change one sample, it Chang its clones too.

Now one important question..
How difficult is to add vst plug-ins to my app?
Like delay echo etc..?

Cheers and good day guys
Code

iWasAdam

my advice would be to do a simple tiny test loop app - get it working and then move the code into your main app.

let's assume you are recording a sound - all you do is overwrite the data in a looping sample that is already playing. a good tip would be to take the sample you are overwriting decrease the volume and then add the new mic sample

Adding vst effect would mean you need to rewrite EVERYTHING to be based on the vst core code.

Adding simple effects would also mean you would need to use your own (as midimaster said) ringbuffer and the code to support effects.

My own approach is to have send busses - these send selected audio into seperate effects units. the result from the units can be mixed back into your output.

I currently use 2 in QasarBeach. But in its predecessor I used 8 programmable ones. the programmables ones used fixed units but with control inputs:

The internal units were a crossover - left/right delay and reverb - reverb crossover and final crossover

these inputs were then collected and given names and graphics:


It was hugely powerful, but I only ever really used 4 at any one time.

But the principal remains the same:
1. take the audio and split it into your dry (the original) mix and a feed into your bus system
2. do whatever you need to do with the bus - this has to be coded to be as fast as possible. so multiple playheads, simple mixing and big buffers are what you need
3. take you dry mix and the wet mix (this is the result from your busses) and mix them into your ringbuffer as the audio out.

an example multi-tap echo could be something along these lines:
Very short simple fast code. using multiple buffers (you can also use a single buffer, but mutiple ones allows you to do strange things with echos and audio)

for l = 0 Until bufferLength-1 Step 2
outBuffer10[l] += outBuffer13[l]
outBuffer13[l] = outBuffer12[l]
outBuffer12[l] = outBuffer11[l]
outBuffer11[l] = fxBusEcho[l] * outDelay

r = l + 1
outBuffer10[r] += outBuffer13[r]
outBuffer13[r] = outBuffer12[r]
outBuffer12[r] = outBuffer11[r]
outBuffer11[r] = fxBusEcho[r] * outDelay2

fxBusEcho[l] = 0
fxBusEcho[r] = 0
Next



iWasAdam

here are a couple of nuggets for you:

1. it's irrelevant how you do something. it's the result that matters
2. thinking of sound as the result you want - then trying to figure out how to get it can be very rewarding - particularly when you come up with a solution that goes against general thinking
3. thinking of a sound as the result from many buffers can give different concepts of what make a sound...

OK.

I think it is also time for you to step back and look at how far you have come.
Decide what has worked and what hasn't. But also what you would like to happen...

If you are thinking that effects is what you really want - then you might have to rethink (code) things - this is good as you can choose a system approach that you think will work for you.

Above all - everything you have learnt so far is now in your toolbox and you can use this knowledge again and again :)

Hardcoal

#108
It is really easy to me to do things..
I mean one of the reasons I dont code too much is because its G damn boring sometimes..
as soon as you find a system of work, it becomes generally easy.. (besides the screen headaches crap)
I force myself to program just to make a progress..
I only begin to enjoy when I pass the basic level.. (Im generally speaking off course)
than when like in my game editor.. its becoming fun when youre adding things beyond the basic structure of the concept..

this music thing was very fun at the start.. now its a bit boring..

anyway enough whining..

If i dont respond to your pervious posts, its just because Its not the time.. Adam and Midi..
Im a very OCD guy.. lots of flooding in my system
I do many things.. Like Welding building coding.. its all one confusion in my life
and I stress myself too much.. because of MY OCD I keep building stuff that i shouldn't

anyway.. again to what ive mentioned long ago..
The Code IDe's are so god damn primitive..
If I knew how to make a proper IDe I would ..
but thats not for now..

I need lots of money and people to do what I ask :) but thats probably on my next life

anyway.. now in my music Editor let me tell you what my problem is ...
I have a track section .. and i can stretch it from one side and from the other side..
so only a section of it can be heard..
but the problem is.. you cant begin playing a track from the middle..
you only have the command playsound..
unless i copy it to a new sample.. which is slow..
I sure wish there was a way to do it without copying..

thats very essential..

And about the VST adding , Adam I didnt see any mentioning on how to do it if at all..

you showed me how to code an effect.. not how to add an external VST.

but this is also Awesome adam. and ill test it soon.


midi master , im gonna experiment with recording while playbacking .. and let you know..

Ill post an image soon.. or even a demo.

Btw this track editing is seperate of my main program that is with the notation and piano keyboard
I will mix them together maybe in the future..

Its too heavy as it is

I made too many editors so things became repetitive..
I should actually make an editor maker..
its so boring making again and again same things..
Like Undo.. Copy, Paste..
We need a system for this ..



Midi master At the moment im recording samples.. and theirs not latency issues with that.
maybe you mean playing midi tools..
yet well.. in that case ill deal with it later..





Code

Midimaster

#109
Quotebut the problem is.. you cant begin playing a track from the middle..
you only have the command playsound..
unless i copy it to a new sample.. which is slow..
I sure wish there was a way to do it without copying..

I cannot confirm that copying the middle of an TAudioSample into a new one does last so long.

Here is a example, that copies 30sec (16bit-Stereo 44.1kHz) from the middle of a TAudioSample into a new one.

I tested three methods.

the classic way runs with 48msec on my computer

The INT_POINTER algo needs only 6msec to do the job, also the BANK algo:

Code (BlitzMax) Select
SuperStrict
' 100 sec of source:
Global A:TAudioSample = CreateAudioSample(44100*100,44100,SF_STEREO16LE)

' 30 sec of new sample
Global B:TAudioSample = CreateAudioSample(44100*30,44100,SF_STEREO16LE)

Global Play:TSound





' now copy 30sec of music from the middle of A to B:
' start at 20th second of A
'


' Method I copy Bytes:
'-------------------------------------------------------
Local time:Int=MilliSecs()
For Local i%=0 To 44100*4*30
  b.Samples[i] = a.Samples[i+44100*20*4]
Next
Play=LoadSound(B)
Print "Method I:............ Copy bytes : " + (MilliSecs()-time) + " msec"



' Method II Copy via INT POINTERs:
'-------------------------------------------------------
time=MilliSecs()
Global A_P:Int Ptr = Int Ptr(A.Samples)
Global B_P:Int Ptr = Int Ptr(B.Samples)

For Local i%=0 To 44100*30
  B_P[i] = A_P[i+44100*20]
Next
Play=LoadSound(B)
Print "Method II: Copy via INT POINTERs : " + (MilliSecs()-time) + " msec"



' Method I copy via BANK:
'-------------------------------------------------------
time=MilliSecs()
Global Bank_A:TBank = CreateStaticBank(A.Samples, A.length*4)
Global Bank_B:TBank = CreateStaticBank(B.Samples, B.length*4)

CopyBank Bank_A , 44100*20*4 , Bank_B ,0 , 44100*4*30
Play=LoadSound(B)
Print "Method III:....... copy via BANK : " + (MilliSecs()-time) + " msec"





Latency

QuoteMidi master At the moment im recording samples.. and theirs not latency issues with that...

You won't run into latency problems until you try to record a second ttrack while playback the first track. Try the following:

1. Record a first take with a simple rhythm on a snare.
2. Now playback the snare track and try to record  the same rhythm on a bell synchron to the snare you listen.
3. Now playback both tracks. You can listen: The bell will not longer be synchron to the snare.
...back from Egypt

iWasAdam

#110
OK 2 questions with 2 similar but different answers
QuoteI sure wish there was a way to do it without copying..
thats very essential..
You need a custom sound core that is built on top of the ring buffer.
in essence you throw out everything you already have and write the system from the ground up to do this.

When you read in your samples from disk - they become a sound store. You then have direct control over how you interact with this sound source, how it is played and accessed.

It becomes a realtime system. the pitch the volume, how the samples is played is all completely written by you and controlled by you.

It's not as hard as it sounds - but you will need help.

Have a look around QasarBeach for more ideas on that front:
https://adamstrange.itch.io/qasarbeach

QuoteAnd about the VST adding , Adam I didnt see any mentioning on how to do it if at all..
There is quite a lot of info about vst writing. BUT (and it's a huge one). You HAVE to use their sound frame work from the start. you can't just plug it in and it's done.
It is related to the first question - if you want vst support you will have to build a system to access the vst sound framework and then build your sound system on top of that. you then have access to vst support. - to my knowledge no one in the blitz community has attempted this. my advice would be tentatively not do this.

As said before that is all very low level stuff...

I know it's not possibly the answers you want to hear - but it is the only ones I can give ;(

You are now at the level where you want direct control over sound - without writing something custom, the base blitz/monkey products become unusable.

Hardcoal

Thanks Adam.
I made a nice progress today.
Soon ill be approaching the latency issue and then ill approach this playing sample from middle issue.
See what i can come up with.
Ill try first using what i got.
I think it's better than rewriting things if i can spare it.
I've already came up with solution as i type.
Soon ill release a little demo.
If you really want to know what im trying to achieve,
Take a look at Mixcraft demo.
That's exactly what im trying to do on the principle level
Code

iWasAdam

QuoteSee what i can come up with.
Ill try first using what i got.
I think it's better than rewriting things if i can spare it.
Absolutely ;)

Just have in the back of your mind that you are hovering around the limits of what can reasonably be achieved.

The next (big) step is to look at rewriting, etc

Hardcoal

#113
It appear like I pulled it off.

All working.. 
off course their are still bugs
but the core idea is working..



Ive managed to do what i planned exactly.. and no.. it was not simple!

now you can take any recorded sample and short it from left or right and it will play it as if its only a section..
and you can always get it back to its original size. so you dont lose any data..

I didnt do Zoom for samples.. and many other things..
but im not sure how far im planing to go with it..

but what  i achieved is already good for me.

ill put a demo after ill fix some errors



Code

Midimaster

can we see the code how you did it?
...back from Egypt

Hardcoal

#115
Sure man..
The thing is the code is spreded over many files..
but ill post some of it and explain what i done..

anyway here is demo..
https://drive.google.com/file/d/1VxmK4YwjIBoaSsG44ReYr_tDaFjuCX5G/view?usp=sharing

Their might be some glitches, one time it created a weird noise.. i dont know why

Atm it displays 10 seconds sample length..


OK.. about how it works..

Well first the sample window is made of two parts the inner part is the image of the sample
and the outer part is a frame that can be shrinked but the sample image remain the same size , but not fully visible.

when I shrink the Sample from the Left side, I cut the sample after shrinking is over and save it on another TAudioSample
but when I shrink from the Right side theirs no need to cut it, just to stop play the sample when The cursor reaches the end of the visible section.

This is how my track Type looks atm


Type TrackSection_Type

Field TrackName:String = "New Track " + CountList(TrackSections_List)
Field TrackType:Type_Class 'Not Used Yet  Midi/Sample..

Field AudioSample:TAudioSample
Field Sound:TSound
Field ShortedSample:TAudioSample 'For Cases you short from the Left

Field Channel:TChannel
Field Volume:Float 'Not in use yet 'There will be a volume General Control Stripe
Field Filename:String = "NewSample.wav"

   'Not Used yet
Field TrackStartPointInSecs:Float
Field TrackVisibleLengthInSecs:Float

   'Alba
    Field TrackScrollArea = alcreategscrollarea(Tracks_Area, "", 0, 0, TrackManagerWidth, TrackScrollAreaHeight, ALF_DontHideScrolls)
Field TrackImage:TexturedButton_Type = Alba.CreateTextureButton(TrackScrollArea, 0, MovePartHeight, GraphicsWdth, TrackSampleAreaHeight)
   'Buttons
    Field PlayButton
Field MuteButton:SwitchButton_Type
Field DeleteButton

   'Flags
    Field IsPlaying_flg
Field PlayingEnded_flg
Field IsMuted_flg = False
Field IsShorted_flg 'When you short from the left

Method Del()
Alba.FreeElement_Mine(MuteButton.MainHandle)
Alba.FreeElement_Mine(PlayButton)
   'Dont Free Element TrackImage.ALHandle atm
Alba.FreeElement_Mine(TrackScrollArea)
End Method

End Type



The shortedSample is the sample that i Play when I shrink it from the Left side..


This is what I use to cut the sample


Function CutSample:TAudioSample(Sample:TAudioSample, StartInSecs:Float, LengthInSecs:Float)
Local T:TAudioSample, StartInBytes, LengthInBytes

StartInBytes = OA.sampleSecsToBytes (Sample, StartInSecs)
LengthInBytes = OA.sampleSecsToBytes (Sample, LengthInSecs)

T = OA.CreateNewTAudioSample(LengthInSecs / 4,Sample.hertz,Sample.format)

Local Counter
For Local I = StartInBytes To StartInBytes + LengthInBytes
If I >= Sample.length * 4 Then Exit
T.samples[Counter] = Sample.samples[I]
Counter = Counter + 1
Next
Return T
End Function



NOW I have an issue with this function.
I made a volume listener before recording begins..
so the recodring will begin when it hear the first sound...
but the problem sometimes it crashes..
can anyone tell me what makes it crash?
or what should i clean before or what should i do to listen to first audio sound
if theirs a better way..

Method ListenToSample()

If RingBuffer.GetSize() >= SampelingChunckSize Then RingBuffer.PeakLast(SamplesBuff, 0, SampelingChunckSize)

alcGetIntegerv(CaptureDevice, ALC_CAPTURE_SAMPLES, 4, Varptr(NumAvailableSamples))

If NumAvailableSamples > 0 Then
alcCaptureSamples(CaptureDevice, Data, NumAvailableSamples)
For Local I:Int = 0 Until NumAvailableSamples
Local Offset:Int = I*2 ' 16 Bit per sample
Local Sample:Float = DecodeSigned16BitLittleEndian(Data, Offset)
RingBuffer.Put(Sample)
Next
EndIf

End Method



* This works for 44100 herz samples..
   I didnt make it to work with other loaded samples of different formats ..
so dont expect it to work on other samples..
it havnt been tested


11:10
-------
ok from this point ill start fixing bugs..
Ive found first bug, when i start record, it begins from the wrong place.. fixing...

23:11
-------
Major bug fixed with recording..
but now i got a new weird bug were it creates annoying static noise..
Its probably some error with my copy sample thing that produces white annoying noise from time to time.






Code

iWasAdam

well done - an interesting way to take a problem and come up with a workable solution. a brilliant example of lateral thinkimg from you - \o/

Hardcoal

Thanks adam.. ^-^  ye i got what i wanted .. for the moment..
from here will see what ill do
Code

Hardcoal

#118
Added new feature, "Track Loop"..
this means it will loop by itself.. independent of the whole track playing



it got its own cursor as can be seen marked by the arrow in the picture
Code

Hardcoal

Code