Returns the number of notes per quarter or per second in a Score as a float.
Specifically, compute note density as (number of notes - 1) divided by
the time span from the first note onset to the last note onset.
The subtraction of 1 ensures that density is measured in terms
of intervals between notes.
If there are no notes, return 0.0.
Author: Tai Nakamura
Parameters:
-
score
(Score)
–
The musical score to analyze.
-
timetype
(str, default:
'quarters'
)
–
Time unit for calculation:
- 'quarters': notes per quarter (default)
- 'seconds' : notes per second
Returns:
-
float
–
Computed note density. Returns 0.0 if the score
is empty or if all notes have the same onset time
(i.e., time span equals zero).
Raises:
-
ValueError
–
If timetype is not 'quarters' or 'seconds'.
Examples:
>>> score = Score.from_melody([60, 62, 64, 65]) # all quarter notes
>>> note_density(score, timetype='quarters')
1.0
>>> from amads.core.timemap import TimeMap
>>> score = Score.from_melody([60, 62, 64, 65]) # all quarter notes
>>> score.time_map = TimeMap(qpm = 120) # set QPM to 120
>>> note_density(score, timetype='seconds')
2.0
>>> score = Score.from_melody([60, 62, 64, 65], durations = [1.0, 2.0, 3.0, 4.0]) # mixed durations
>>> note_density(score, timetype='quarters')
0.5
Source code in amads/time/notedensity.py
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90 | def note_density(score: Score, timetype: Optional[str] = "quarters") -> float:
"""
Returns the number of notes per quarter or per second in a Score as a float.
Specifically, compute note density as (number of notes - 1) divided by
the time span from the first note onset to the last note onset.
The subtraction of 1 ensures that density is measured in terms
of intervals between notes.
If there are no notes, return 0.0.
<small>**Author**: Tai Nakamura</small>
Parameters
----------
score : Score
The musical score to analyze.
timetype : str, optional, default='quarters'
Time unit for calculation:
- 'quarters': notes per quarter (default)
- 'seconds' : notes per second
Returns
-------
float
Computed note density. Returns 0.0 if the score
is empty or if all notes have the same onset time
(i.e., time span equals zero).
Raises
------
ValueError
If `timetype` is not 'quarters' or 'seconds'.
Examples
--------
>>> score = Score.from_melody([60, 62, 64, 65]) # all quarter notes
>>> note_density(score, timetype='quarters')
1.0
>>> from amads.core.timemap import TimeMap
>>> score = Score.from_melody([60, 62, 64, 65]) # all quarter notes
>>> score.time_map = TimeMap(qpm = 120) # set QPM to 120
>>> note_density(score, timetype='seconds')
2.0
>>> score = Score.from_melody([60, 62, 64, 65], durations = [1.0, 2.0, 3.0, 4.0]) # mixed durations
>>> note_density(score, timetype='quarters')
0.5
"""
notes = score.get_sorted_notes()
if not notes:
return 0.0
if timetype == "seconds":
if score.units_are_seconds:
start_onset = notes[0].onset
end_onset = notes[-1].onset
else:
start_onset = score.time_map.quarter_to_time(notes[0].onset)
end_onset = score.time_map.quarter_to_time(notes[-1].onset)
elif timetype == "quarters":
if score.units_are_seconds:
start_onset = score.time_map.time_to_quarter(notes[0].onset)
end_onset = score.time_map.time_to_quarter(notes[-1].onset)
else:
start_onset = notes[0].onset
end_onset = notes[-1].onset
else:
raise ValueError(
f"Invalid timetype: {timetype}. Use 'quarters' or 'seconds'."
)
duration = end_onset - start_onset
if duration <= 0:
return 0.0
return (len(notes) - 1) / duration
|