Skip to content

Commit

Permalink
Added Python properties for Note's setters and getters
Browse files Browse the repository at this point in the history
I hope that keeping the set_x and get_x functions still keep compatibility to older versions, but now it has Python property.

Updated readme for this commit as well.
  • Loading branch information
UtaUtaUtau committed Feb 23, 2021
1 parent 36520c3 commit af3a57c
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 29 deletions.
49 changes: 25 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,32 +137,33 @@ A class that stores note data.
These are written for data that UTAU can send in and read.
Some of them get initializers because UTAU sends in values for them.
**NOTE:** All floating point data are rounded to 3 decimals when set. Sorry if you still wanted to keep precision.
**NOTE pt. 2:** If a property has both a setter and a getter, it's got a Python property setup for it. For example, since Lyric has both a setter and a getter, its property is named `lyric`. The `set_lyric` and `get_lyric` functions still exist for backwards compatibility, I hope. The table will list the property names, even if it doesn't have a setter. The format is just `set_x`, `get_x`, and `init_x` where `x` is the property name.

Legend: **Required**, Not Required, *Read-only*
Data Key | Description | Setter | Getter | Initializer | Value Type
--- | --- | :---: | :---: | :---: | :---:
**Length** | Note Length. 480 = 1 quarter note. | `set_length(self, length)` | `get_length(self)` | - | `int`
**Lyric** | Note Lyric. | `set_lyric(self, lyric)` | `get_lyric(self)` | `init_lyric(self)` | `str`
**NoteNum** | Note key. C4 = 60 | `set_note_num(self, note_num)`| `get_note_num(self)` | - | `int`
**PreUtterance** | Note pre-utterance in milliseconds. | `set_preutterance(self, preutterance)` | `get_preutterance(self)` | `init_preutterance(self)` | `float`
VoiceOverlap | Note overlap in milliseconds. | `set_overlap(self, overlap)` | `get_overlap(self)` | `init_overlap(self)` | `float`
Intensity | Note intensity in percent. | `set_intensity(self, intensity)` | `get_intensity(self)` | - | `float`
Modulation | Note modulation in percent. | `set_modulation(self, modulation)` | `get_modulation(self)` | - | `float`
StartPoint | Note start point/time in milliseconds. | `set_start_point(self, start_point)` | `get_start_point(self)` | `init_start_point(self)` | `float`
Envelope | Note envelope. | `set_envelope(self, envelope)` | `get_envelope(self)` | - | `Envelope`
Tempo | Tempo at note in BPM. | `set_tempo(self, tempo)` | `get_tempo(self)` | - | `float`
Velocity | Note consonant velocity in percent. | `set_velocity(self, velocity)` | `get_velocity(self)` | - | `float`
Label | Label at note. | `set_label(self, label)` | `get_label(self, label)` | - | `str`
$direct | Boolean that enables direct rendering. | `set_direct(self, direct)` | `get_direct(self)` | - | `bool`
PBS, PBW, PBY, PBM | Mode 2 pitchbend data. | `set_mode2pitch(self, mode2pitch)` | `get_mode2pitch(self)` | - | `Mode2Pitch`
VBR | Mode 2 vibrato data. | `set_vibrato(self, vibrato)` | `get_vibrato(self)` | - | `Vibrato`
PitchBend, PBStart | Mode 1 pitchbend data. | `set_mode1pitch(self, mode1pitch)` | `get_mode1pitch(self)` | - | `Mode1Pitch`
*@preuttr* | Re-calculated pre-utterance in milliseconds. | - | `get_at_preutterance(self)` | - | `float`
*@overlap* | Re-calculated overlap in milliseconds. | - | `get_at_overlap(self)` | - | `float`
*@stpoint* | Calculated start point in milliseconds. | - | `get_at_start_point(self)` | - | `float`
*@filename* | Filename of sample. | - | `get_sample_filename(self)` | - | `str`
*@alias* | Alias with prefix map applied. Can also have VCV applied for shareware. | - | `get_alias(self)` | - | `str`
*@cache* | Note cache file path. Not present when the note has no cache. | - | `get_cache_location(self)` | - | `str`
Data Key | Property Name | Description | Getter | Setter | Initializer | Value Type
--- | --- | --- | :---: | :---: | :---: | :---:
**Length** | `length` | Note Length. 480 = 1 quarter note. | ✓ | ✓ | - | `int`
**Lyric** | `lyric` | Note Lyric. | ✓ | ✓ | | `str`
**NoteNum** | `note_num` | Note key. C4 = 60 | ✓ | ✓ | - | `int`
**PreUtterance** | `preutterance` | Note pre-utterance in milliseconds. | ✓ | ✓ | | `float`
VoiceOverlap | `overlap` | Note overlap in milliseconds. | ✓ | ✓ | | `float`
Intensity | `intensity` | Note intensity in percent. | ✓ | ✓ | - | `float`
Modulation | `modulation` | Note modulation in percent. | ✓ | ✓ | - | `float`
StartPoint | `start_point` | Note start point/time in milliseconds. | ✓ | ✓ | | `float`
Envelope | `envelope` | Note envelope. | ✓ | ✓ | - | `Envelope`
Tempo | `tempo` | Tempo at note in BPM. | ✓ | ✓ | - | `float`
Velocity | `velocity` | Note consonant velocity in percent. | ✓ | ✓ | - | `float`
Label | `label` | Label at note. | ✓ | ✓ | - | `str`
$direct | `direct` | Boolean that enables direct rendering. | ✓ | ✓ | - | `bool`
PBS, PBW, PBY, PBM | `mode2pitch` | Mode 2 pitchbend data. | ✓ | ✓ | - | `Mode2Pitch`
VBR | `vibrato` | Mode 2 vibrato data. | ✓ | ✓ | - | `Vibrato`
PitchBend, PBStart | `mode1pitch` | Mode 1 pitchbend data. | ✓ | ✓ | - | `Mode1Pitch`
*@preuttr* | `at_preutterance` | Re-calculated pre-utterance in milliseconds. | | - | - | `float`
*@overlap* | `at_overlap` | Re-calculated overlap in milliseconds. | | - | - | `float`
*@stpoint* | `at_start_point` | Calculated start point in milliseconds. | | - | - | `float`
*@filename* | `sample_filename` | Filename of sample. | | - | - | `str`
*@alias* | `alias` | Alias with prefix map applied. Can also have VCV applied for shareware. | | - | - | `str`
*@cache* | `cache_location` | Note cache file path. Not present when the note has no cache. | | - | - | `str`

Envelope
-----
Expand Down
42 changes: 37 additions & 5 deletions pyutau.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,12 +249,16 @@ def set_length(self, length):
def get_length(self):
return int(self.note_data['Length'])

length = property(get_length, set_length)

def set_lyric(self, lyric):
self.note_data['Lyric'] = lyric

def get_lyric(self):
return self.note_data['Lyric']

lyric = property(get_lyric, set_lyric)

def init_lyric(self):
#This sets the lyric to what it is with the prefix map applied.
#Probably VCV as well for those who use AutoVCV in Shareware
Expand All @@ -267,6 +271,8 @@ def set_note_num(self, note_num):
def get_note_num(self):
return int(self.note_data['NoteNum'])

note_num = property(get_note_num, set_note_num)

def set_preutterance(self, preutterance):
#Some might prefer using decimals.
#This isn't as elegant as {preutterance:.3g} but it switches to e when needed
Expand All @@ -277,10 +283,12 @@ def get_preutterance(self):
#The PreUtterance value can be blank, but is required.
#The way I store this blank is by making it None.
if self.note_data['PreUtterance']:
return int(self.note_data['PreUtterance'])
return float(self.note_data['PreUtterance'])
else:
return None

preutterance = property(get_preutterance, set_preutterance)

def init_preutterance(self):
#UTAU sends in preutterance values, this initializes it on the PreUtterance data
#Is obsolete for INSERT notes unless somehow you generate the read-only data
Expand All @@ -292,12 +300,14 @@ def set_overlap(self, overlap):
self.note_data['VoiceOverlap'] = f'{overlap:.3f}'.rstrip('0').rstrip('.')

def get_overlap(self):
#TODO: Get overlap from @overlap or just check VoiceOverlap?
#Get overlap from @overlap or just check VoiceOverlap?
if 'VoiceOverlap' in self.note_data:
return self.note_data['VoiceOverlap']
return float(self.note_data['VoiceOverlap'])
else:
return None

overlap = property(get_overlap, set_overlap)

def init_overlap(self):
#Same for init_preutterance
self.note_data['VoiceOverlap'] = self.note_data['@overlap']
Expand All @@ -311,6 +321,8 @@ def get_intensity(self):
else:
return None

intensity = property(get_intensity, set_intensity)

def set_modulation(self, modulation):
self.note_data['Modulation'] = f'{modulation:.3f}'.rstrip('0').rstrip('.')

Expand All @@ -320,16 +332,20 @@ def get_modulation(self):
else:
return None

modulation = property(get_modulation, set_modulation)

def set_start_point(self, start_point):
self.note_data['StartPoint'] = f'{start_point:.3f}'.rstrip('0').rstrip('.')

def get_start_point(self, start_point):
#TODO: Same as get_overlap
#Same as get_overlap
if 'StartPoint' in self.note_data:
return float(self.note_data['StartPoint'])
else:
return None

start_point = property(get_start_point, set_start_point)

def init_start_point(self):
self.note_data['StartPoint'] = self.note_data['@stpoint']

Expand All @@ -343,6 +359,8 @@ def get_envelope(self):
else:
return None

envelope = property(get_envelope, set_envelope)

def set_tempo(self, tempo):
self.note_data['Tempo'] = f'{tempo:.3f}'.rstrip('0').rstrip('.')

Expand All @@ -352,6 +370,8 @@ def get_tempo(self):
else:
return None

tempo = property(get_tempo, set_tempo)

def set_velocity(self, velocity):
self.note_data['Velocity'] = f'{velocity:.3f}'.rstrip('0').rstrip('.')

Expand All @@ -361,15 +381,19 @@ def get_velocity(self):
else:
return None

velocity = property(get_velocity, set_velocity)

def set_label(self, label):
self.note_data['Label'] = label

def get_label(self):
if 'Label' in self.note_data:
return float(self.note_data['Velocity'])
return self.note_data['Label']
else:
return None

label = property(get_label, set_label)

def set_direct(self, direct):
self.note_data['$direct'] = str(direct).lower()

Expand All @@ -379,6 +403,8 @@ def get_direct(self):
else:
return None

direct = property(get_direct, set_direct)

def set_mode2pitch(self, mode2pitch):
if isinstance(mode2pitch, Mode2Pitch):
self.set_multiple_data(**mode2pitch.get())
Expand All @@ -396,6 +422,8 @@ def get_mode2pitch(self):
else:
return None

mode2pitch = property(get_mode2pitch, set_mode2pitch)

def set_vibrato(self, vibrato):
self.note_data['VBR'] = str(vibrato)

Expand All @@ -405,6 +433,8 @@ def get_vibrato(self):
else:
return None

vibrato = property(get_vibrato, set_vibrato)

def set_mode1pitch(self, mode1pitch):
if isinstance(mode1pitch, Mode1Pitch):
self.set_multiple_data(**mode1pitch.get())
Expand All @@ -423,6 +453,8 @@ def get_mode1pitch(self):
else:
return None

mode1pitch = property(get_mode1pitch, set_mode1pitch)

#Getters for read-only data. All of these start with @
def get_at_preutterance(self):
return float(self.note_data['@preuttr'])
Expand Down

0 comments on commit af3a57c

Please sign in to comment.