Page 1 of 1
Sound-Editing like StartDrawing()
Posted: Fri Feb 07, 2025 10:39 am
by jamirokwai
Hi there,
I'd like to propose new options for working with sound. Since PB switched to the miniaudio-lib, it might be possible
What, if we could edit audio like images? I mean, do something like (with a better named command than StartSounding():
Code: Select all
define mySound = CreateSound(#pb_any, 2000, 16, 2, 48000) ; 2000 msecs, 16 Bits, Stereo, 48000 Hz
if StartSounding(SoundOutput(mySound))
debug SoundBuffer() ; directly access sound-data
debug SoundBufferBitFormat() ; display bits per sample
debug SoundBufferPitch() ; display size of one sample
debug SoundBufferChannels() ; 2 = stereo
debug SoundBufferRate() ; e.g. 48000
StopSounding()
endif
I already wished for some things, as I hit some walls while coding...
Expose more MiniAudio-Functions
Audio-Filter - please try, comment, optimise, notify bugs
pl_mpeg.h and decoding question
Posting the structure of a PB-sound would be a great start.
Addition (2025-02-08) (after some thoughts and the comment by infratec):
Possible functions:
Code: Select all
define mySound = CreateSound(#pb_any, 2000, 16, 2, 48000) ; creates an empty buffer, 2000 msecs, 16 Bits, Stereo, 48000 Hz
ResizeSound(SoundID, newlength_in_msecs) ; make changing bits, channels, samplerate also possible?
SaveSound(SoundID, "export.wav", #pb_soundformat_wav) ; save as .wav as minimum, .ogg, etc. possible?
StartRingBuffer(SoundID) ; prepare a ring buffer
SetRingbufferCallback(@FilterCallback()) ; is called, when a part of the ring buffer has finished playing, so you can fill it again
CustomSoundFilterCallback(@SoundFilterCallback()) ; like CustomFilterCallback
Re: Sound-Editing like StartDrawing()
Posted: Fri Feb 07, 2025 12:48 pm
by Quin
Massive +1. Being able to generate and play songs entirely from within PB for example all with tones would be great!
Re: Sound-Editing like StartDrawing()
Posted: Sat Feb 08, 2025 2:21 am
by threedslider
Great ! +100
Re: Sound-Editing like StartDrawing()
Posted: Sat Feb 08, 2025 10:20 am
by infratec
And how sounds your CreateSound
What should be inside of the sound?
How you want to specify the sound curve?
At the moment your CreateSound() can create an empty sound which returns silence.
To make something lke that universal, you need a lot of stuff around.
This would result in a synthesizer where you can draw your waves.
But this is not doable inside of a program.
Tools for this:
https://vital.audio/
https://tal-software.com/products/tal-noisemaker
Also OpenMPT can draw own 'samples'
Create new opnempt file, go to samples, press the pencil button, insert siolence, then you can modify the curve.
Or you are restricted to sine, square and saw curves.
I already posted examples how to create such sounds via code.
Re: Sound-Editing like StartDrawing()
Posted: Sat Feb 08, 2025 10:29 am
by jamirokwai
infratec wrote: Sat Feb 08, 2025 10:20 am
And how sounds your CreateSound
What should be inside of the sound?
How you want to specify the sound curve?
At the moment your CreateSound() can create an empty sound which returns silence.
To make something lke that universal, you need a lot of stuff around.
This would result in a synthesizer where you can draw your waves.
But this is not doable inside of a program.
A good tool for this:
https://vital.audio/
Or you are restricted to sine, square and saw curves.
I already posted examples how to create such sounds via code.
Yes, create an empty sound, like CreateImage. That sound should be resizable in length and may be exported as a .wav.
I totally agree: Purebasic should only lay the foundation. The coder or user has to be responsible for putting viable sound-data into the buffer, adding effects, filtering, exporting as .ogg, you name it.
I added some function-ideas in the first post.
Re: Sound-Editing like StartDrawing()
Posted: Sat Feb 08, 2025 11:04 am
by infratec
Your first wish is done.
CreateSound:
Code: Select all
CompilerIf #PB_Compiler_IsMainFile
EnableExplicit
CompilerEndIf
Structure RIFFStructure
Riff.a[4]
Length.l
Wave.a[4]
EndStructure
Structure fmtStructure
fmt.a[4]
Length.l
Format.u
Channels.u
SampleRate.l
BytesPerSecond.l
BlockAlign.u
BitsPerSample.u
EndStructure
Structure dataStructure
Signature.a[4]
Length.l
EndStructure
Procedure.i CreateSound(Sound.i, Duration.i, Bits.i=16, Channels.i=2, SamplingRate.i=48000)
Protected.i Result, HeaderSize, DataSize
Protected *WAVBuffer, *RiffPtr.RIFFStructure, *fmtPtr.fmtStructure, *dataPtr.dataStructure, *audioPtr
HeaderSize = SizeOf(RIFFStructure)
HeaderSize + SizeOf(fmtStructure)
HeaderSize + SizeOf(dataStructure)
DataSize = (Bits / 8) * SamplingRate * Duration * Channels / 1000
*WAVBuffer = AllocateMemory(HeaderSize + DataSize, #PB_Memory_NoClear)
If *WAVBuffer
*RiffPtr = *WAVBuffer
PokeS(@*RiffPtr\Riff, "RIFF", 4, #PB_Ascii|#PB_String_NoZero)
*RiffPtr\Length = HeaderSize + DataSize - 8
PokeS(@*RiffPtr\Wave, "WAVE", 4, #PB_Ascii|#PB_String_NoZero)
*fmtPtr = *WAVBuffer + SizeOf(RIFFStructure)
PokeS(@*fmtPtr\fmt, "fmt ", 4, #PB_Ascii|#PB_String_NoZero)
*fmtPtr\Length = SizeOf(fmtStructure) - 8
*fmtPtr\Format = 1
*fmtPtr\Channels = Channels
*fmtPtr\SampleRate = SamplingRate
*fmtPtr\BitsPerSample = Bits
*fmtPtr\BlockAlign = *fmtPtr\Channels * ((*fmtPtr\BitsPerSample + 7) / 8)
*fmtPtr\BytesPerSecond = *fmtPtr\SampleRate * *fmtPtr\BlockAlign
*dataPtr = *WAVBuffer + SizeOf(RIFFStructure) + SizeOf(fmtStructure)
PokeS(@*dataPtr\Signature, "data", 4, #PB_Ascii|#PB_String_NoZero)
*dataPtr\Length = DataSize
*audioPtr = *WAVBuffer + SizeOf(RIFFStructure) + SizeOf(fmtStructure) + SizeOf(dataStructure) ; just behind the wav header
; If CreateFile(0, "test.wav")
; WriteData(0, *WAVBuffer, MemorySize(*WAVBuffer))
; CloseFile(0)
; EndIf
Result = CatchSound(Sound, *WAVBuffer)
FreeMemory(*WAVBuffer)
EndIf
ProcedureReturn Result
EndProcedure
CompilerIf #PB_Compiler_IsMainFile
Define Sound.i, Start.q
InitSound()
Sound = CreateSound(#PB_Any, 2000, 16, 2, 48000) ; 2000 msecs, 16 Bits, Stereo, 48000 Hz
If Sound
Debug "Sound Created and playing"
PlaySound(Sound)
Start = ElapsedMilliseconds()
While SoundStatus(Sound) = #PB_Sound_Playing
Delay(1)
Wend
Debug "Duration: " + Str(ElapsedMilliseconds() - Start) + "ms"
FreeSound(Sound)
Else
Debug "Was not able to create sound."
EndIf
CompilerEndIf
You can check the result by comment out the writing to file and open it with AudaCity.
Re: Sound-Editing like StartDrawing()
Posted: Sat Feb 08, 2025 7:19 pm
by Mijikai
+1