You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
2.6 KiB
118 lines
2.6 KiB
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"embed"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/chzyer/readline"
|
|
"github.com/gopxl/beep"
|
|
"github.com/gopxl/beep/speaker"
|
|
"github.com/gopxl/beep/wav"
|
|
)
|
|
|
|
//go:embed sound/*
|
|
var soundFS embed.FS
|
|
|
|
const (
|
|
pauseBetweenCharacters = 500 * time.Millisecond
|
|
longPause = 1600 * time.Millisecond
|
|
)
|
|
|
|
func main() {
|
|
// Create a map to store sound data for each character
|
|
soundMap := make(map[rune][]byte)
|
|
|
|
// Load all sound files into the map
|
|
for _, c := range "abcdefghijklmnopqrstuvwxyz0123456789" {
|
|
filename := fmt.Sprintf("sound/sam%c.wav", c)
|
|
data, err := soundFS.ReadFile(filename)
|
|
if err == nil {
|
|
soundMap[c] = data
|
|
}
|
|
}
|
|
|
|
// Configure readline settings
|
|
rl, err := readline.NewEx(&readline.Config{
|
|
Prompt: "> ", // Use a simple prompt for each line input
|
|
InterruptPrompt: "^C",
|
|
EOFPrompt: "exit",
|
|
FuncFilterInputRune: uppercaseFilter, // Filter to show uppercase
|
|
})
|
|
if err != nil {
|
|
fmt.Printf("Error initializing readline: %s\n", err)
|
|
return
|
|
}
|
|
defer rl.Close()
|
|
|
|
// Inform the user about how to enter input
|
|
fmt.Println("Enter lines of text (press Enter on a blank line to finish):")
|
|
|
|
var inputBuilder strings.Builder
|
|
for {
|
|
line, err := rl.Readline()
|
|
if err != nil {
|
|
if err.Error() == "EOF" {
|
|
fmt.Println("Exiting.")
|
|
return
|
|
}
|
|
fmt.Printf("Error reading input: %s\n", err)
|
|
return
|
|
}
|
|
|
|
// Check if the user entered a blank line to finish input
|
|
if strings.TrimSpace(line) == "" {
|
|
break
|
|
}
|
|
|
|
// Append the line to the input builder
|
|
inputBuilder.WriteString(line + "\n")
|
|
}
|
|
|
|
// Get the complete input as a string
|
|
input := inputBuilder.String()
|
|
input = strings.ToLower(strings.TrimSpace(input))
|
|
|
|
for _, c := range input {
|
|
if c == '-' || c == '_' || c == ' ' || c == '\n' {
|
|
time.Sleep(longPause)
|
|
} else {
|
|
if soundData, ok := soundMap[c]; ok {
|
|
playSound(soundData)
|
|
} else {
|
|
fmt.Printf("No sound file found for character: %c\n", c)
|
|
}
|
|
time.Sleep(pauseBetweenCharacters)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Function to play sound
|
|
func playSound(soundData []byte) {
|
|
streamer, format, err := wav.Decode(bytes.NewReader(soundData))
|
|
if err != nil {
|
|
fmt.Printf("Could not decode sound data: %s\n", err)
|
|
return
|
|
}
|
|
defer streamer.Close()
|
|
|
|
speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10))
|
|
done := make(chan bool)
|
|
speaker.Play(beep.Seq(streamer, beep.Callback(func() {
|
|
done <- true
|
|
})))
|
|
|
|
<-done
|
|
}
|
|
|
|
// Filter function to convert all typed input to uppercase for display
|
|
func uppercaseFilter(r rune) (rune, bool) {
|
|
if r >= 'a' && r <= 'z' {
|
|
return r - ('a' - 'A'), true // Convert to uppercase
|
|
}
|
|
return r, true // Keep other characters unchanged
|
|
}
|
|
|