From 943a61f359f28e9d5203edf02834f72cbf8dc895 Mon Sep 17 00:00:00 2001 From: Trek H Date: Thu, 10 Mar 2022 16:18:26 +1030 Subject: [PATCH] spectrogram: add golang spectrogram generator --- exp/spectrogram/main.go | 126 ++++++++++++++++++++++++++++++++++++++++ go.mod | 2 + go.sum | 4 ++ 3 files changed, 132 insertions(+) create mode 100644 exp/spectrogram/main.go diff --git a/exp/spectrogram/main.go b/exp/spectrogram/main.go new file mode 100644 index 00000000..5a6d2d8e --- /dev/null +++ b/exp/spectrogram/main.go @@ -0,0 +1,126 @@ +/* +DESCRIPTION + + +AUTHORS + Trek Hopton + +LICENSE + Copyright (C) 2020 the Australian Ocean Lab (AusOcean) + + It is free software: you can redistribute it and/or modify them + under the terms of the GNU General Public License as published by the + Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + It is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + in gpl.txt. If not, see http://www.gnu.org/licenses. +*/ + +// Package spectrogram is a program that generates a spectrogram given an audio file. +// package main + +package main + +import ( + "flag" + "fmt" + "image" + "image/draw" + "log" + "os" + + "github.com/trekhopton/spectrogram" + "github.com/xigh/go-wavreader" +) + +func main() { + flag.Parse() + + if flag.NArg() == 0 { + fmt.Printf("usage: fft [options] file.wav\n") + return + } + + name := flag.Arg(0) + + r, err := os.Open(name) + if err != nil { + log.Fatal(err) + } + defer r.Close() + + wr, err := wavreader.New(r) + if err != nil { + log.Fatal(err) + } + + fmt.Printf("%s: %dHz, %d channels, %d samples, %v\n", + name, wr.Rate(), wr.Chans(), wr.Len(), wr.Duration()) + + start := *spectrogram.OFFSET + if start > wr.Len() { + log.Fatalf("offset bigger than file") + } + + length := *spectrogram.LENGTH + if start+length > wr.Len() { + log.Printf("length too long\n") + length = wr.Len() - start + } + + length = wr.Len() + samples := make([]float64, length) + for i := uint64(0); i < length; i++ { + s, err := wr.At(0, start+i) + if err != nil { + log.Fatal(err) + } + samples[i] = float64(s) + } + + if *spectrogram.PREEMP > 0 { + for i := len(samples) - 1; i > 0; i-- { + samples[i] = samples[i] - *spectrogram.PREEMP*samples[i-1] + } + } + + W := int(*spectrogram.WIDTH) + H := int(*spectrogram.HEIGHT) + B := int(*spectrogram.BINS) + + bounds := image.Rect(-20, -20, W+20, H+40+B) + img := spectrogram.NewImage128(bounds) + + bg0 := spectrogram.ParseColor(*spectrogram.BG0) + fmt.Printf("bg0: %.8x\n", bg0) + draw.Draw(img, img.Bounds(), image.NewUniform(bg0), image.ZP, draw.Src) + + fmt.Println("drawwav:") + i0 := img.Sub(image.Rect(0, 0, W, H)) + spectrogram.Drawwav(i0, samples) + + fmt.Println("drawfft:") + i1 := img.Sub(image.Rect(0, H+20, W, H+20+B)) + spectrogram.Drawfft(i1, samples, wr.Rate(), uint32(B)) + + a0, s0 := img.Stats() + fmt.Printf("img stats: %d reads, %d writes\n", a0, s0) + + fmt.Printf("saving %q\n", *spectrogram.OUT) + + err = spectrogram.SavePng(img, *spectrogram.OUT) + if err != nil { + log.Fatalf("savePng failed: %v", err) + } + + fmt.Printf("saved %q\n", *spectrogram.OUT) + + a1, s1 := img.Stats() + fmt.Printf("img stats: %d reads, %d writes\n", a1, s1) +} diff --git a/go.mod b/go.mod index 16f5c3c3..4443787b 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,8 @@ require ( github.com/kidoman/embd v0.0.0-20170508013040-d3d8c0c5c68d github.com/mewkiz/flac v1.0.5 github.com/pkg/errors v0.9.1 + github.com/trekhopton/spectrogram v1.0.0 + github.com/xigh/go-wavreader v0.0.0-20210516212152-f49019aa7352 github.com/yobert/alsa v0.0.0-20180630182551-d38d89fa843e gocv.io/x/gocv v0.29.0 gonum.org/v1/gonum v0.9.3 diff --git a/go.sum b/go.sum index 7c028dfa..c5e8ab22 100644 --- a/go.sum +++ b/go.sum @@ -83,6 +83,10 @@ github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/trekhopton/spectrogram v1.0.0 h1:Y1+G+oTDtNCrnuEjgm91s8Uyi0dF6vjwB+VTLECPoKw= +github.com/trekhopton/spectrogram v1.0.0/go.mod h1:ea0tlSV7WC0Rqq9PcY2DGN88Lw13lAhCOPFUK8U/2zk= +github.com/xigh/go-wavreader v0.0.0-20210516212152-f49019aa7352 h1:iK7SnIgPre4wrUN7HpIhZpfP7884mcc7CQS3FeyGTes= +github.com/xigh/go-wavreader v0.0.0-20210516212152-f49019aa7352/go.mod h1:SiPEYpvfimzIRkLfaOYXVNGbQGVmgQZ6BQHcKyj/iic= github.com/yobert/alsa v0.0.0-20180630182551-d38d89fa843e h1:3NIzz7weXhh3NToPgbtlQtKiVgerEaG4/nY2skGoGG0= github.com/yobert/alsa v0.0.0-20180630182551-d38d89fa843e/go.mod h1:CaowXBWOiSGWEpBBV8LoVnQTVPV4ycyviC9IBLj8dRw= github.com/yryz/ds18b20 v0.0.0-20180211073435-3cf383a40624/go.mod h1:MqFju5qeLDFh+S9PqxYT7TEla8xeW7bgGr/69q3oki0=