Skip to content

Commit

Permalink
feat: POC
Browse files Browse the repository at this point in the history
  • Loading branch information
moul committed Oct 24, 2019
1 parent 8ba5d73 commit d2bc129
Show file tree
Hide file tree
Showing 5 changed files with 255 additions and 8 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
.DS_Store
out.mp3

# Temporary files
*~
*#
Expand Down
5 changes: 5 additions & 0 deletions go.mod

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

87 changes: 87 additions & 0 deletions go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

162 changes: 160 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,165 @@
package main

import "fmt"
import (
"errors"
"flag"
"fmt"
"log"
"math/rand"
"os"
"os/exec"
"sort"
"strings"

packr "github.com/gobuffalo/packr/v2"
"github.com/peterbourgon/ff/ffcli"
)

var (
sayBox = packr.New("say", "./say")
pronounceBox = packr.New("pronounce", "./pronounce")
)

func main() {
fmt.Println("Hello World!")
log.SetFlags(0)

var (
sayFlags = flag.NewFlagSet("say", flag.ExitOnError)
sayVoice = sayFlags.String("v", "RANDOM", "voice")

pronounceFlags = flag.NewFlagSet("pronounce", flag.ExitOnError)
pronounceVoice = pronounceFlags.String("v", "RANDOM", "voice")
)

pronounce := &ffcli.Command{
Name: "pronounce",
Usage: "pronounce [-v VOICE] PRONOUNCE",
FlagSet: pronounceFlags,
LongHelp: fmt.Sprintf("VOICES\n %s", strings.Join(append(voiceList(pronounceBox), "RANDOM"), "\n ")),
Exec: func(args []string) error {
if len(args) < 1 {
return flag.ErrHelp
}
parts := voiceParts(pronounceBox, *pronounceVoice)

tosay := []rune(strings.Join(args, " "))

selectedParts := []string{}

for i := 0; i < len(tosay); {
maxLen := 0
selectedPart := ""
for partString := range parts {
part := []rune(partString)
if len(part) <= maxLen {
continue
}
if string(part) == string(tosay[i:i+len(part)]) {
maxLen = len(part)
selectedPart = string(part)
}
}
if selectedPart != "" {
i += maxLen
selectedParts = append(selectedParts, selectedPart)
} else {
i++ // skip unmatched parts
}
}

selectedFiles := []string{}

for _, part := range selectedParts {
randomFile := parts[part][rand.Intn(len(parts[part]))]
selectedFiles = append(selectedFiles, fmt.Sprintf("./pronounce/%s", randomFile))
}

cmdArgs := append(selectedFiles, "out.mp3")
log.Printf("+ sox %s", strings.Join(cmdArgs, " "))
cmd := exec.Command("sox", cmdArgs...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return err
}

log.Printf("+ afplay out.mp3")
cmd = exec.Command("afplay", "out.mp3")
if err := cmd.Run(); err != nil {
return err
}

return nil
},
}

say := &ffcli.Command{
Name: "say",
Usage: "say [-v VOICE] SAY",
FlagSet: sayFlags,
LongHelp: fmt.Sprintf("VOICES\n %s", strings.Join(append(voiceList(sayBox), "RANDOM"), "\n ")),
Exec: func(args []string) error {
if len(args) < 1 {
return flag.ErrHelp
}
_ = sayVoice
return fmt.Errorf("not implemented")
},
}

root := &ffcli.Command{
Usage: "speechotron <subcommand> [flags] [args...]",
Subcommands: []*ffcli.Command{pronounce, say},
Exec: func([]string) error { return flag.ErrHelp },
}

if err := root.Run(os.Args[1:]); err != nil {
if errors.Is(err, flag.ErrHelp) {
return
}
log.Fatalf("fatal: %+v", err)
}
}

func voiceList(box *packr.Box) []string {
voices := map[string]bool{}
for _, voice := range box.List() {
if !strings.HasSuffix(voice, ".wav") {
continue
}
voices[strings.Split(voice, "/")[0]] = true
}

ret := []string{}
for voice := range voices {
ret = append(ret, voice)
}
sort.Strings(ret)

return ret
}

func voiceParts(box *packr.Box, voice string) map[string][]string {
ret := map[string][]string{}

for _, file := range box.List() {
if !strings.HasSuffix(file, ".wav") {
continue
}

spl := strings.Split(file, "/")
actualVoice := spl[0]
if voice != "RANDOM" && voice != actualVoice {
continue
}

part := strings.Replace(spl[1], ".wav", "", -1)

if _, ok := ret[part]; !ok {
ret[part] = []string{}
}
ret[part] = append(ret[part], file)
}

return ret
}
6 changes: 0 additions & 6 deletions main_test.go

This file was deleted.

0 comments on commit d2bc129

Please sign in to comment.