120 lines
3.2 KiB
Python
120 lines
3.2 KiB
Python
from pprint import pprint
|
|
|
|
"""
|
|
Not all output rates are going to be supported by the system sound card.
|
|
Choosing from a limited subset of preferred output rates is how we guarantee
|
|
that the system will be able to play the output audio.
|
|
Sample rates stolen from:
|
|
https://en.wikipedia.org/wiki/Sampling_(signal_processing)
|
|
"""
|
|
supported_ouput_rates = [
|
|
8000, # Telephone, P25 audio (sufficient for speech, some consonants unintelligble)
|
|
16000, # Modern telephone/VoIP, good quality speech
|
|
32000, # FM radio
|
|
44100, # CD audio quality
|
|
48000,
|
|
50000, # Uncommon but supported
|
|
88200,
|
|
96000, # DVD/Blu-ray audio
|
|
192000, # Too much.
|
|
]
|
|
|
|
def score(pair, target_output=32000, target_ratio=10):
|
|
"""
|
|
Heuristic for scoring input & output sample rates. The criteria are:
|
|
- closest to 44.1 kHz is better;
|
|
- closer to a ratio of 10 is better,
|
|
- additionally penalising ratios lower than 10.
|
|
|
|
Lower scores are better.
|
|
|
|
This should result in selected sample rates that give good audio quality
|
|
without wasting CPU cycles on a needlessly high input rate.
|
|
"""
|
|
|
|
# Give the worst score possible for impossible pairs.
|
|
if pair[0] % pair[1] != 0:
|
|
return float("inf")
|
|
|
|
ratio = pair[0] // pair[1]
|
|
|
|
return abs(pair[1] - target_output)/2500 \
|
|
+ max(0, target_output - pair[1])/2500 \
|
|
+ abs(ratio - target_ratio)**0.8 \
|
|
+ max(0, target_ratio - ratio)**2
|
|
|
|
def flatten(l):
|
|
return [item for sublist in l for item in sublist]
|
|
|
|
def flatten_dict(d):
|
|
return [(key,value) for key,rates in d.items() for value in rates]
|
|
|
|
def get_pairs(input_rate):
|
|
return [
|
|
(input_rate, rate)
|
|
for rate in supported_ouput_rates
|
|
if (input_rate % rate == 0)
|
|
]
|
|
|
|
def supported_sample_rates(supported_input_rates):
|
|
return {
|
|
in_rate: [out_rate for out_rate in supported_ouput_rates if in_rate % out_rate == 0]
|
|
for in_rate in supported_input_rates
|
|
}
|
|
|
|
def preferred_sample_rates(supported_input_rates):
|
|
return sorted(flatten_dict(supported_sample_rates(supported_input_rates)), key=score)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
nesdr_sample_rates = [
|
|
250000,
|
|
1024000,
|
|
1536000,
|
|
1792000,
|
|
1920000,
|
|
2048000,
|
|
2160000,
|
|
2560000,
|
|
2880000,
|
|
3200000
|
|
]
|
|
|
|
sdrplay_sample_rates = [
|
|
62500,
|
|
96000,
|
|
125000,
|
|
192000,
|
|
250000,
|
|
384000,
|
|
500000,
|
|
768000,
|
|
1000000,
|
|
2000000,
|
|
2048000,
|
|
3000000,
|
|
4000000,
|
|
5000000,
|
|
6000000,
|
|
7000000,
|
|
8000000,
|
|
9000000,
|
|
10000000
|
|
]
|
|
|
|
print('nesdr')
|
|
pprint(preferred_sample_rates(nesdr_sample_rates))
|
|
#for rate in nesdr_sample_rates:
|
|
# print(rate, ' \t', get_pairs(rate))
|
|
#supported = flatten([get_pairs(rate) for rate in nesdr_sample_rates])
|
|
#supported.sort(key=score)
|
|
#pprint(supported)
|
|
|
|
print('sdrplay')
|
|
pprint(preferred_sample_rates(sdrplay_sample_rates))
|
|
#for rate in sdrplay_sample_rates:
|
|
# print(rate, ' \t', get_pairs(rate))
|
|
#supported = flatten([get_pairs(rate) for rate in sdrplay_sample_rates])
|
|
#supported.sort(key=score)
|
|
#pprint(supported)
|