summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Perry <avaglir@gmail.com>2017-07-28 00:51:34 -0400
committerNathan Perry <avaglir@gmail.com>2017-07-28 00:51:34 -0400
commit47877a3045c745e70b2e77a91e1f59e6f432c5df (patch)
treedfcb8b1ea145c33c04aee45dd0c46824bf5fec36
parent54359c61daadf1d61730d224675c3b4595a5b83a (diff)
try own wav impl
-rw-r--r--downloader/downloader.go80
-rw-r--r--downloader/downloader_test.go22
-rw-r--r--extramemes.go14
-rw-r--r--wav/wav.go177
-rw-r--r--wav/wav_test.go15
5 files changed, 308 insertions, 0 deletions
diff --git a/downloader/downloader.go b/downloader/downloader.go
new file mode 100644
index 0000000..1ebaa1d
--- /dev/null
+++ b/downloader/downloader.go
@@ -0,0 +1,80 @@
+package downloader
+
+import (
+ "net/url"
+ "os/exec"
+ "strconv"
+ "time"
+
+ "io/ioutil"
+ "os"
+
+ "github.com/cryptix/wav"
+ "github.com/op/go-logging"
+)
+
+var log = logging.MustGetLogger("downloader")
+
+func getUrl(inUrl string) (string, error) {
+ dl := exec.Command("youtube-dl", "-f", "bestaudio", "-x", "--get-url", inUrl)
+
+ b, err := dl.CombinedOutput()
+ if err != nil {
+ log.Errorf("youtube-dl failed: %v", string(b))
+ return "", err
+ }
+
+ tgt, err := url.Parse(string(b))
+ out := tgt.Scheme + "://" + tgt.Host + tgt.Path + "?" + tgt.Query().Encode()
+
+ return out, nil
+}
+
+func Download(inUrl string, startTime time.Duration, duration time.Duration) error {
+ targetUrl, err := getUrl(inUrl)
+ if err != nil {
+ return err
+ }
+
+ startSecond := int(startTime.Seconds())
+ dur := int(duration.Seconds())
+
+ args := []string{
+ "-ss", strconv.Itoa(startSecond),
+ "-i", targetUrl,
+ "-c:a", "pcm_s16le",
+ "-f", "wav",
+ "-ar", "44100",
+ "-ac", "2",
+ "-vn", "-y",
+ }
+
+ if dur > 0 {
+ args = append(args, "-t", strconv.Itoa(dur))
+ }
+
+ file, err := ioutil.TempFile("", "dl")
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err := os.Remove(file.Name()); err != nil {
+ log.Errorf("unable to remove temp file: %q", err)
+ }
+ }()
+
+ args = append(args, file.Name())
+
+ dl := exec.Command(`ffmpeg`, args...)
+ b, err := dl.CombinedOutput()
+ if err != nil {
+ log.Errorf("ffmpeg failed: \n%v", string(b))
+ return err
+ }
+
+ wav.NewReader(file, )
+
+
+
+ return nil
+}
diff --git a/downloader/downloader_test.go b/downloader/downloader_test.go
new file mode 100644
index 0000000..37a23d4
--- /dev/null
+++ b/downloader/downloader_test.go
@@ -0,0 +1,22 @@
+package downloader
+
+import (
+ "fmt"
+ "testing"
+ "time"
+)
+
+func TestGetUrl(t *testing.T) {
+ u, err := getUrl("https://www.youtube.com/watch?v=_K13GJkGvDw")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ fmt.Println(u)
+}
+
+func TestDownload(t *testing.T) {
+ if err := Download("https://www.youtube.com/watch?v=_K13GJkGvDw", 10*time.Second, 10*time.Second); err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/extramemes.go b/extramemes.go
index 4bac256..fb2f8f6 100644
--- a/extramemes.go
+++ b/extramemes.go
@@ -2,6 +2,7 @@ package thulani
import (
"math/rand"
+ "regexp"
"strings"
"time"
)
@@ -13,6 +14,7 @@ func init() {
var extraMemes = []func(*messageCtx) MemeStatus{
respondToFuckYou,
respondToMeme,
+ respondToRaaaaaaaaaaaay,
}
var hateMatch = []string{
@@ -70,3 +72,15 @@ func respondToMeme(ctx *messageCtx) MemeStatus {
ctx.sendMessage("i am not yet capable of memeing.", false)
return Interrupt
}
+
+var ray = regexp.MustCompile("ra+y")
+
+// TODO: play the sound clip
+func respondToRaaaaaaaaaaaay(ctx *messageCtx) MemeStatus {
+ if ctx.Matched && ray.MatchString(ctx.Command) {
+ ctx.sendMessage(ctx.Command, true)
+ return Interrupt
+ }
+
+ return Continue
+}
diff --git a/wav/wav.go b/wav/wav.go
new file mode 100644
index 0000000..b82ec16
--- /dev/null
+++ b/wav/wav.go
@@ -0,0 +1,177 @@
+package wav
+
+import (
+ "bytes"
+ "encoding/binary"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+)
+
+type WavFile struct {
+ Header Header
+ Format FormatChunk
+ Data DataChunk
+}
+
+type Header struct {
+ GroupID [4]uint8
+ FileLength uint32
+ RiffType [4]uint8
+}
+
+type FormatChunk struct {
+ GroupID [4]uint8
+ ChunkSize uint32
+ FormatTag uint16
+ Channels uint16
+ SampleRate uint32
+ ByteRate uint32
+ Alignment uint16
+ BitDensity uint32
+}
+
+type DataChunk struct {
+ GroupID [4]uint8
+ ChunkSize uint32
+ Samples io.Reader
+}
+
+func Load(filename string) (*WavFile, error) {
+ file, err := os.Open(filename)
+
+ if err != nil {
+ return nil, err
+ }
+
+ load16 := func(b []byte) (uint16, error) {
+ var out uint16
+ err := binary.Read(bytes.NewBuffer(b), binary.LittleEndian, &out)
+ return out, err
+ }
+
+ load32 := func(b []byte) (uint32, error) {
+ var out uint32
+ err := binary.Read(bytes.NewBuffer(b), binary.LittleEndian, &out)
+ return out, err
+
+ }
+
+ b, err := ioutil.ReadAll(io.LimitReader(file, 40))
+ if err != nil {
+ return nil, err
+ }
+
+ h := Header{}
+ h.FileLength, err = load32(b[4:36])
+ if err != nil {
+ return nil, err
+ }
+ h.FileLength -= 8 // subtract RIFF/WAVE markers
+
+ for i := 0; i < 4; i++ {
+ h.GroupID[i] = b[i]
+ h.RiffType[i] = b[i+36]
+ }
+
+ fmt.Println(h)
+ fmt.Println(string(h.RiffType[:]))
+
+ if string(h.GroupID[:]) != "RIFF" { // || string(h.RiffType[:]) != "WAVE" {
+ return nil, fmt.Errorf("invalid header!")
+ }
+
+ f := FormatChunk{}
+
+ file.Seek(40, io.SeekStart)
+ b, err = ioutil.ReadAll(io.LimitReader(file, 36))
+ if err != nil {
+ return nil, err
+ }
+
+ for i := 0; i < 4; i++ {
+ f.GroupID[i] = b[i]
+ }
+
+ f.ChunkSize, err = load32(b[4:36])
+ if err != nil {
+ return nil, err
+ }
+
+ file.Seek(76, io.SeekStart)
+ b, err = ioutil.ReadAll(io.LimitReader(file, int64(f.ChunkSize)))
+ if err != nil {
+ return nil, err
+ }
+
+ f.FormatTag, err = load16(b[36:52])
+ if err != nil {
+ return nil, err
+ }
+
+ f.Channels, err = load16(b[52:68])
+ if err != nil {
+ return nil, err
+ }
+
+ f.SampleRate, err = load32(b[68:100])
+ if err != nil {
+ return nil, err
+ }
+
+ f.ByteRate, err = load32(b[100:132])
+ if err != nil {
+ return nil, err
+ }
+
+ f.Alignment, err = load16(b[132:148])
+ if err != nil {
+ return nil, err
+ }
+
+ f.BitDensity, err = load32(b[138:180])
+ if err != nil {
+ return nil, err
+ }
+
+ if string(f.GroupID[:]) != "fmt " ||
+ f.FormatTag != 1 ||
+ f.Alignment != uint16((uint32(f.Channels)*f.BitDensity/8)&0xff) {
+ return nil, fmt.Errorf("invalid format block!")
+ }
+
+ if f.BitDensity != 16 || f.Channels != 2 || f.SampleRate != 44100 {
+ return nil, fmt.Errorf("wrong pcm format!")
+ }
+
+ d := DataChunk{}
+
+ file.Seek(220, io.SeekStart)
+ b, err = ioutil.ReadAll(io.LimitReader(file, 36))
+ if err != nil {
+ return nil, err
+ }
+
+ for i := 0; i < 4; i++ {
+ d.GroupID[i] = b[i]
+ }
+
+ d.ChunkSize, err = load32(b[4:])
+ if err != nil {
+ return nil, err
+ }
+
+ if string(f.GroupID[:]) != "fmt " {
+ return nil, fmt.Errorf("invalid data block!")
+ }
+
+ file.Seek(256, io.SeekStart)
+ d.Samples = io.LimitReader(file, int64(d.ChunkSize))
+
+ return &WavFile{
+ Header: h,
+ Format: f,
+ Data: d,
+ }, nil
+}
diff --git a/wav/wav_test.go b/wav/wav_test.go
new file mode 100644
index 0000000..4fa64db
--- /dev/null
+++ b/wav/wav_test.go
@@ -0,0 +1,15 @@
+package wav
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestLoad(t *testing.T) {
+ wf, err := Load("../downloader/out.wav")
+ if err != nil {
+ t.Error(err)
+ }
+
+ fmt.Println(wf)
+}