<commit_before>package core

import (
	"bytes"
	"fmt"
	"io"
	"regexp"
	"strconv"
	"strings"

	"github.com/emicklei/melrose/notify"
)

// Note represents a musical note.
// Notations:
// 		½C♯.3 = half duration, pitch C, sharp, octave 3, velocity default (70)
//		D     = quarter duration, pitch D, octave 4, no accidental
//      ⅛B♭  = eigth duration, pitch B, octave 4, flat
//		=     = quarter rest
//      -/+   = velocity number
// http://en.wikipedia.org/wiki/Musical_Note
type Note struct {
	Name       string // {C D E F G A B = }
	Octave     int    // [0 .. 9]
	Accidental int    // -1 Flat, +1 Sharp, 0 Normal
	Dotted     bool   // if true then reported duration is increased by half
	Velocity   int    // 1..127

	duration float32 // {0.0625,0.125,0.25,0.5,1}
}

func (n Note) Storex() string {
	return fmt.Sprintf("note('%s')", n.String())
}

// ToNote() is part of NoteConvertable
func (n Note) ToNote() Note {
	return n
}

func (n Note) ToRest() Note {
	return Note{
		Name:       "=",
		Octave:     n.Octave,
		Accidental: n.Accidental,
		Dotted:     n.Dotted,
		Velocity:   n.Velocity,
		duration:   n.duration,
	}
}

// Replaced is part of Replaceable
func (n Note) Replaced(from, to Sequenceable) Sequenceable {
	if IsIdenticalTo(from, n) {
		return to
	}
	return n
}

var (
	Rest4 = Note{Name: "=", duration: 0.25}
)

var rest = Note{Name: "="}

func NewNote(name string, octave int, duration float32, accidental int, dot bool, velocity int) (Note, error) {
	if len(name) != 1 {
		return rest, fmt.Errorf("note must be one character, got [%s]", name)
	}
	if !strings.Contains("ABCDEFG=", name) {
		return rest, fmt.Errorf("invalid note name [ABCDEFG=]:" + name)
	}
	if octave < 0 || octave > 9 {
		return rest, fmt.Errorf("invalid octave [0..9]:" + string(octave))
	}
	switch duration {
	case 0.0625:
	case 0.125:
	case 0.25:
	case 0.5:
	case 1:
	default:
		return rest, fmt.Errorf("invalid duration [1,0.5,0.25,0.125,0.0625]:%v\n", duration)
	}

	if accidental != 0 && accidental != -1 && accidental != 1 {
		return rest, fmt.Errorf("invalid accidental :" + string(accidental))
	}

	return Note{Name: name, Octave: octave, duration: duration, Accidental: accidental, Dotted: dot, Velocity: velocity}, nil
}

func (n Note) IsRest() bool { return "=" == n.Name }

func (n Note) Length() float32 {
	if n.Dotted {
		return n.duration * 1.5
	}
	return n.duration
}

func (n Note) S() Sequence {
	return BuildSequence([]Note{n})
}

// TODO rename
func (n Note) ModifiedVelocity(velo int) Note {
	nn, _ := NewNote(n.Name, n.Octave, n.duration, n.Accidental, n.Dotted, velo)
	return nn
}

func (n Note) WithDuration(dur float64, dotted bool) Note {<commit_msg>fix rune conversion<commit_after>package core

import (
	"bytes"
	"fmt"
	"io"
	"regexp"
	"strconv"
	"strings"

	"github.com/emicklei/melrose/notify"
)

// Note represents a musical note.
// Notations:
// 		½C♯.3 = half duration, pitch C, sharp, octave 3, velocity default (70)
//		D     = quarter duration, pitch D, octave 4, no accidental
//      ⅛B♭  = eigth duration, pitch B, octave 4, flat
//		=     = quarter rest
//      -/+   = velocity number
// http://en.wikipedia.org/wiki/Musical_Note
type Note struct {
	Name       string // {C D E F G A B = }
	Octave     int    // [0 .. 9]
	Accidental int    // -1 Flat, +1 Sharp, 0 Normal
	Dotted     bool   // if true then reported duration is increased by half
	Velocity   int    // 1..127

	duration float32 // {0.0625,0.125,0.25,0.5,1}
}

func (n Note) Storex() string {
	return fmt.Sprintf("note('%s')", n.String())
}

// ToNote() is part of NoteConvertable
func (n Note) ToNote() Note {
	return n
}

func (n Note) ToRest() Note {
	return Note{
		Name:       "=",
		Octave:     n.Octave,
		Accidental: n.Accidental,
		Dotted:     n.Dotted,
		Velocity:   n.Velocity,
		duration:   n.duration,
	}
}

// Replaced is part of Replaceable
func (n Note) Replaced(from, to Sequenceable) Sequenceable {
	if IsIdenticalTo(from, n) {
		return to
	}
	return n
}

var (
	Rest4 = Note{Name: "=", duration: 0.25}
)

var rest = Note{Name: "="}

func NewNote(name string, octave int, duration float32, accidental int, dot bool, velocity int) (Note, error) {
	if len(name) != 1 {
		return rest, fmt.Errorf("note must be one character, got [%s]", name)
	}
	if !strings.Contains("ABCDEFG=", name) {
		return rest, fmt.Errorf("invalid note name [ABCDEFG=]:" + name)
	}
	if octave < 0 || octave > 9 {
		return rest, fmt.Errorf("invalid octave [0..9]: %d", octave)
	}
	switch duration {
	case 0.0625:
	case 0.125:
	case 0.25:
	case 0.5:
	case 1:
	default:
		return rest, fmt.Errorf("invalid duration [1,0.5,0.25,0.125,0.0625]:%v\n", duration)
	}

	if accidental != 0 && accidental != -1 && accidental != 1 {
		return rest, fmt.Errorf("invalid accidental: %d", accidental)
	}

	return Note{Name: name, Octave: octave, duration: duration, Accidental: accidental, Dotted: dot, Velocity: velocity}, nil
}

func (n Note) IsRest() bool { return "=" == n.Name }

func (n Note) Length() float32 {
	if n.Dotted {
		return n.duration * 1.5
	}
	return n.duration
}

func (n Note) S() Sequence {
	return BuildSequence([]Note{n})
}

// TODO rename
func (n Note) ModifiedVelocity(velo int) Note {
	nn, _ := NewNote(n.Name, n.Octave, n.duration, n.Accidental, n.Dotted, velo)
	return nn
}

func (n Note) WithDuration(dur float64, dotted bool) Note {
{'fraction_non_alphanumeric': 0.1513959153082256, 'fraction_numerical': 0.030728873899194303, 'mean_word_length': 3.1638065522620904, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1913456', 'n_tokens_mistral': 2150, 'n_tokens_neox': 1990, 'n_words': 604}