You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'd like to reproduce sound using a speaker like the example below because I want to simulate a piano.
package main
import (
"fmt""math""os""os/signal""time""github.com/gopxl/beep""github.com/gopxl/beep/speaker"
)
constsampleRate=44100funcmain() {
duration:=1*time.Second// Duração do som (por exemplo, 1 segundo)// Configuração do formato do somformat:=beep.SampleRate(sampleRate)
speaker.Init(format, format.N(time.Second/10))
// Mapa de frequências para as notas musicaisnoteFrequencies:=map[string]float64{
"DO": 261.63,
"RE": 293.66,
"MI": 329.63,
"FA": 349.23,
"SOL": 392.00,
"LA": 440.00,
"SI": 493.88,
// DO RE MI FA FA DO RE DO RE RE DO SOL FA MI MI DO RE MI FA FA
}
doremifa:= []string{
"DO", "RE", "MI", "FA", "FA", "DO", "RE", "DO",
"RE", "RE", "DO", "SOL", "FA", "MI", "MI", "DO", "RE",
"MI", "FA", "FA",
}
// Tocar as notas musicaisfor_, note:=rangedoremifa {
playNoteWithCleanSignal(note, noteFrequencies[note], duration)
}
fmt.Println("Finished playing notes.")
}
// playNoteWithCleanSignal toca uma nota musical específica com sinal limpofuncplayNoteWithCleanSignal(notestring, frequencyfloat64, duration time.Duration) {
// Gerar streamer para a nota especificadastreamer:=beep.StreamerFunc(func(samples [][2]float64) (nint, okbool) {
fori:=rangesamples {
t:=float64(i) /sampleRate// Aplicar um envelope de amplitude para suavizar o início e o fim da notaamplitude:=math.Sin(2*math.Pi*frequency*t) *envelope(float64(i), duration.Seconds()*sampleRate)
samples[i][0] =amplitude*0.3// Ajuste de volumesamples[i][1] =samples[i][0] // Canal estéreo
}
returnlen(samples), true
})
// Tocar o somdone:=make(chanbool)
speaker.Play(beep.Seq(streamer, beep.Callback(func() {
done<-true
})))
fmt.Printf("Playing note %s (%.2f Hz) for %s...\n", note, frequency, duration)
// Esperar até que a duração expire ou até que o usuário pressione Ctrl+Cselect {
case<-time.After(duration):
case<-interrupt():
}
fmt.Printf("Note %s finished playing.\n", note)
}
funcenvelope(ifloat64, lengthfloat64) float64 {
attack:=0.1// duração do ataque (em porcentagem da duração total)decay:=0.1// duração da queda (em porcentagem da duração total)sustain:=0.7// nível de sustentação (em porcentagem do nível máximo)release:=0.1// duração da liberação (em porcentagem da duração total)attackSamples:=int(attack*length)
decaySamples:=int(decay*length)
sustainSamples:=int(sustain*length)
releaseSamples:=int(release*length)
ifi<float64(attackSamples) {
returnfloat64(i) /float64(attackSamples)
} elseifi<float64(attackSamples+decaySamples) {
return1- (i-float64(attackSamples)/float64(decaySamples)*(1-sustain))
} elseifi<float64(attackSamples+decaySamples+sustainSamples) {
returnsustain
} else {
returnsustain- (i-float64(attackSamples)-float64(decaySamples)-float64(sustainSamples))/(float64(releaseSamples)*sustain)
}
}
funcinterrupt() chan os.Signal {
c:=make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
returnc
}
The text was updated successfully, but these errors were encountered:
The above snippet shows a StreamerFunc. How speaker and a lot of Beep's components work is that they only pull a small amount of samples (e.g. 512 samples) from the streamer at a time to save on memory. Therefor, StreamerFunc will be called multiple times and each time it receives a slice with a small amount of samples to fill. If i is used as the time for the sine wave, the sine wave will start over each time, and this could cause glitch noises. What you'll need to do is keep track of the total number of samples played over the course of multiple calls to StreamerFunc. If that makes sense.
Just so you know, generators.SineTone() exists. But if you want to add the envelop function it may be a bit more difficult.
Try debugging your code first without the envelope. I think envelope doesn't work as well yet so first try to make the rest of the program work and not do everything at once.
This doesn't stop the sound from playing. This will send a signal on the done channel when the streamer is finished (but it never finishes), and done isn't used. So at the end all tones are still playing. Have a look at beep.Take() or make sure the StreamerFunc returns an end signal. Then you could use done in the select statement instead of time.After().
I'd like to reproduce sound using a speaker like the example below because I want to simulate a piano.
The text was updated successfully, but these errors were encountered: