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)