Skip to content

Commit

Permalink
Merge pull request #16 from sopro-dev/enh/new-proposal-structure
Browse files Browse the repository at this point in the history
Enh/new proposal structure
  • Loading branch information
pablodz authored Jan 2, 2024
2 parents 7802b53 + f536a3b commit 23b2ef1
Show file tree
Hide file tree
Showing 84 changed files with 583 additions and 3,065 deletions.
2 changes: 1 addition & 1 deletion .deepsource.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ test_patterns = ["**/*_test.go"]
name = "go"

[analyzers.meta]
import_root = "github.com/pablodz/sopro"
import_root = "github.com/sopro-dev/sopro-core"
2 changes: 1 addition & 1 deletion .github/workflows/tagger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: tagger
on:
push:
branches:
- "*"
- "main"

jobs:
tagger:
Expand Down
55 changes: 54 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,57 @@

# Dependency directories (remove the comment below to include it)
# vendor/
executable
executable

## All files with audio format
# Ignore standart audio files
*.3gp
*.aa
*.aac
*.aax
*.act
*.aiff
*.alac
*.amr
*.ape
*.au
*.awb
*.dss
*.flac
*.gsm
*.m4a
*.m4b
*.m4p
*.mp3
*.mpc
*.ogg
*.oga
*.mogg
*.ulaw
*.opus
*.pcm
*.ra
*.rm
*.raw
*.rf64
*.sln
*.tta
*.voc
*.vox
*.wav
*.wma
*.webm
*.8svx
*.cda
# Ignore raw audio files
*.raw
*.wv
*.mid
*.midi
*.mod
*.mpa
*.mp1
*.mp2
*.mp3
*.ul
*.al
2 changes: 1 addition & 1 deletion .version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v0.1.4
v0.2.1
1 change: 0 additions & 1 deletion AUTHORS

This file was deleted.

2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2023 Pablo & SoPro Authors
Copyright (c) 2024 Pablo & SoPro Authors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
25 changes: 9 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[![Go Report Card](https://goreportcard.com/badge/github.com/pablodz/sopro)](https://goreportcard.com/report/github.com/pablodz/sopro)
[![Go Report Card](https://goreportcard.com/badge/github.com/sopro-dev/sopro-core)](https://goreportcard.com/report/github.com/sopro-dev/sopro-core)

# SoPro (next generation SOund PROcessing)

Expand Down Expand Up @@ -28,17 +28,15 @@ Examples:
Plugins:
- Connectivity to python neural network inference api with grpc/http and caching the inference

## Example (WIP)

Trascoding a file from ulaw to wav pcm with CLI

[![asciicast](https://asciinema.org/a/IXy7MLb1qyXDCCU7IUsrdVkmA.svg)](https://asciinema.org/a/IXy7MLb1qyXDCCU7IUsrdVkmA)
## Warning

- HTTP & gRPC Server and cli are on new roadmap


## Installation

```bash
go get -v github.com/pablodz/sopro
go get -v github.com/sopro-dev/sopro-core
```

## Contribution
Expand All @@ -65,7 +63,7 @@ Check [./examples](./examples/) folder
- [ ] Websocket
- [ ] gRPC
- [x] Audio file conversion
- [ ] Format conversion [Work in progress...](docs/format_table.md)
- [ ] Format conversion (Work in progress...)
- [ ] Bitrate conversion
- [ ] Channels conversion
- [ ] Resampling
Expand Down Expand Up @@ -160,17 +158,12 @@ Check [./examples](./examples/) folder
- [ ] Two channel mixer
- [ ] Multi channel mixer
- [ ] Debugger
- [x] Audio ascii graph in terminal
- [x] Headers viewer in terminal
- [ ] Audio ascii graph in terminal
- [ ] Headers viewer in terminal
- [ ] spectrogram: graph signal level vs. frequency & time
- [ ] stat: Enumerate audio peak & RMS levels, approx. freq., etc.
- [ ] stats: Multichannel aware `stat'


## Authors

All authors that contributed to this project are listed in the [AUTHORS](AUTHORS) file.

## License

SoPro is licensed under the [MIT License](LICENSE).
SoPro is licensed under the [MIT License](LICENSE).
14 changes: 14 additions & 0 deletions audio/audio.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package audio

type AudioInfo struct {
SampleRate int
Channels int
BitDepth int
FloatFormat bool
Verbose bool
}

type AudioFormat interface {
Decode(data []byte, info AudioInfo) []byte
Encode(audioData []byte, info AudioInfo) []byte
}
25 changes: 25 additions & 0 deletions audio/formats/pcm/pcm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// audio/formats/pcm/pcm.go
package pcm

import (
"log"

"github.com/sopro-dev/sopro-core/audio"
)

type PCMFormat struct{}

func (f *PCMFormat) Decode(data []byte, info audio.AudioInfo) []byte {
log.Printf("Not implemented")
return nil
}

func (f *PCMFormat) Encode(audioData []byte, info audio.AudioInfo) []byte {
// convert float64 to byte
data := make([]byte, len(audioData))
for i := 0; i < len(audioData); i++ {
data[i] = byte(audioData[i])
}

return data
}
34 changes: 34 additions & 0 deletions audio/formats/ulaw/mulaw.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package mulaw

import (
"log"

"github.com/sopro-dev/sopro-core/audio"
"github.com/sopro-dev/sopro-core/audio/utils"
)

type MuLawFormat struct{}

func (f *MuLawFormat) Decode(data []byte, info audio.AudioInfo) []byte {
pcmData := make([]byte, len(data)*2)
// remember that each byte need to be converted to two bytes
for i := 0; i < len(data); i++ {

newFrame := utils.DecodeULawToPCM(data[i : i+1])
pcmData[i*2] = newFrame[0]
pcmData[i*2+1] = newFrame[1]

}
if info.Verbose {
log.Println("[MuLaw][Decode] Decoded to PCM")
log.Println("[MuLaw][Decode] PCM Data [0 :100]", pcmData[0:100])
log.Println("[MuLaw][Decode] PCM Data [100:200]", pcmData[100:200])
}

return pcmData
}

func (f *MuLawFormat) Encode(audioData []byte, info audio.AudioInfo) []byte {
log.Printf("Not implemented")
return nil
}
53 changes: 53 additions & 0 deletions audio/transcoder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package audio

import (
"errors"
"unsafe"
)

type Transcoder struct {
InputFormat AudioFormat
OutputFormat AudioFormat
}

func NewTranscoder(inputFormat, outputFormat AudioFormat) *Transcoder {
return &Transcoder{
InputFormat: inputFormat,
OutputFormat: outputFormat,
}
}

func (t *Transcoder) Transcode(inputData []byte, info AudioInfo) ([]byte, error) {
err := validateAudioInfo(info)
if err != nil {
return nil, err
}
audioData := t.InputFormat.Decode(inputData, info)
return t.OutputFormat.Encode(audioData, info), nil
}

var (
errInvalidBitDepth = errors.New("invalid bit depth")
errInvalidNumChannels = errors.New("invalid number of channels")
errInvalidSampleRate = errors.New("invalid sample rate")
)

func validateAudioInfo(info AudioInfo) error {
if info.BitDepth != 8 && info.BitDepth != 16 && info.BitDepth != 24 && info.BitDepth != 32 {
return errInvalidBitDepth
}

if info.Channels < 1 || info.Channels > 2 {
return errInvalidNumChannels
}

if info.SampleRate < 1 {
return errInvalidSampleRate
}
return nil
}

// IMPORTANT: DO NOT REMOVE THIS LINE
// This line validates the size of the int16 type on the current platform,
// panics if the size is not 2 bytes.
var _ [unsafe.Sizeof(int16(0))]struct{}
42 changes: 42 additions & 0 deletions audio/transcoder_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package audio

import "testing"

func TestValidateAudioInfo(t *testing.T) {
// Test case 1: Valid audio info
info := AudioInfo{BitDepth: 16, Channels: 2, SampleRate: 44100}
err := validateAudioInfo(info)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}

// Test case 2: Invalid bit depth
info = AudioInfo{BitDepth: 5, Channels: 2, SampleRate: 44100}
err = validateAudioInfo(info)
if err == nil {
t.Error("Expected an error for invalid bit depth")
}
if err != errInvalidBitDepth {
t.Errorf("Expected error %v, got %v", errInvalidBitDepth, err)
}

// Test case 3: Invalid number of channels
info = AudioInfo{BitDepth: 16, Channels: 0, SampleRate: 44100}
err = validateAudioInfo(info)
if err == nil {
t.Error("Expected an error for invalid number of channels")
}
if err != errInvalidNumChannels {
t.Errorf("Expected error %v, got %v", errInvalidNumChannels, err)
}

// Test case 4: Invalid sample rate
info = AudioInfo{BitDepth: 16, Channels: 2, SampleRate: 0}
err = validateAudioInfo(info)
if err == nil {
t.Error("Expected an error for invalid sample rate")
}
if err != errInvalidSampleRate {
t.Errorf("Expected error %v, got %v", errInvalidSampleRate, err)
}
}
31 changes: 31 additions & 0 deletions audio/utils/bytes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package utils

import (
"encoding/binary"
)

// MergeSliceOfBytes merges multiple slices of bytes into a single slice
func MergeSliceOfBytes(slices ...[]byte) []byte {
var result []byte
for _, s := range slices {
result = append(result, s...)
}
return result
}

// IntToBytes converts an unsigned integer to a little-endian byte slice
func IntToBytes(i interface{}) []byte {
switch v := i.(type) {
case uint32:
buf := make([]byte, 4)
binary.LittleEndian.PutUint32(buf, v)
return buf
case uint16:
buf := make([]byte, 2)
binary.LittleEndian.PutUint16(buf, v)
return buf
default:

}
return nil
}
Loading

0 comments on commit 23b2ef1

Please sign in to comment.