-
Notifications
You must be signed in to change notification settings - Fork 25
Open
Description
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"
)
const sampleRate = 44100
func main() {
duration := 1 * time.Second // Duração do som (por exemplo, 1 segundo)
// Configuração do formato do som
format := beep.SampleRate(sampleRate)
speaker.Init(format, format.N(time.Second/10))
// Mapa de frequências para as notas musicais
noteFrequencies := 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 musicais
for _, note := range doremifa {
playNoteWithCleanSignal(note, noteFrequencies[note], duration)
}
fmt.Println("Finished playing notes.")
}
// playNoteWithCleanSignal toca uma nota musical específica com sinal limpo
func playNoteWithCleanSignal(note string, frequency float64, duration time.Duration) {
// Gerar streamer para a nota especificada
streamer := beep.StreamerFunc(func(samples [][2]float64) (n int, ok bool) {
for i := range samples {
t := float64(i) / sampleRate
// Aplicar um envelope de amplitude para suavizar o início e o fim da nota
amplitude := math.Sin(2*math.Pi*frequency*t) * envelope(float64(i), duration.Seconds()*sampleRate)
samples[i][0] = amplitude * 0.3 // Ajuste de volume
samples[i][1] = samples[i][0] // Canal estéreo
}
return len(samples), true
})
// Tocar o som
done := make(chan bool)
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+C
select {
case <-time.After(duration):
case <-interrupt():
}
fmt.Printf("Note %s finished playing.\n", note)
}
func envelope(i float64, length float64) 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)
if i < float64(attackSamples) {
return float64(i) / float64(attackSamples)
} else if i < float64(attackSamples+decaySamples) {
return 1 - (i - float64(attackSamples)/float64(decaySamples)*(1-sustain))
} else if i < float64(attackSamples+decaySamples+sustainSamples) {
return sustain
} else {
return sustain - (i-float64(attackSamples)-float64(decaySamples)-float64(sustainSamples))/(float64(releaseSamples)*sustain)
}
}
func interrupt() chan os.Signal {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
return c
}Metadata
Metadata
Assignees
Labels
No labels