SHARE
TWEET

NetMDPython dump_md.py mod 24-bit / 96 kHz

remim Apr 22nd, 2018 (edited) 112 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/python
  2. # Look at lines #10, #89 and #120 for PRECISION, SAMPLERATE (#89) and for the ENCODER at lines #10 and #120 where the values should be the same; among those provided by SoX.
  3. import os
  4. import usb1
  5. import libnetmd
  6. from time import sleep
  7. import platform
  8. import subprocess
  9.  
  10. def main(bus=None, device_address=None, ext='ogg', track_range=None,
  11. title=None):
  12.     context = usb1.LibUSBContext()
  13.     for md in libnetmd.iterdevices(context, bus=bus,
  14.                                    device_address=device_address):
  15.         md_iface = libnetmd.NetMDInterface(md)
  16.         try:
  17.             MDDump(md_iface, ext, track_range, title)
  18.         finally:
  19.             md_iface.stop()
  20.  
  21. def getTrackList(md_iface, track_range):
  22.     result = []
  23.     append = result.append
  24.     track_count = md_iface.getTrackCount()
  25.     if isinstance(track_range, tuple):
  26.         min_track, max_track = track_range
  27.         if max_track is None:
  28.             max_track = track_count - 1
  29.         assert max_track < track_count
  30.         assert min_track < track_count
  31.         track_list = xrange(min_track, max_track + 1)
  32.     elif isinstance(track_range, int):
  33.         assert track_range < track_count
  34.         track_list = [track_range]
  35.     else:
  36.         track_list = xrange(track_count)
  37.     for track in track_list:
  38.         hour, minute, second, sample = md_iface.getTrackLength(track)
  39.         codec, channel_count = md_iface.getTrackEncoding(track)
  40.         channel_count = libnetmd.CHANNEL_COUNT_DICT[channel_count]
  41.         ascii_title = md_iface.getTrackTitle(track)
  42.         wchar_title = md_iface.getTrackTitle(track, True).decode('shift_jis')
  43.         title = wchar_title or ascii_title
  44.         append((track,
  45.                 (hour, minute, second, sample),
  46.                 str(channel_count),
  47.                 title))
  48.     return result
  49.  
  50. def MDDump(md_iface, ext, track_range, disk_title_override=None):
  51.     if disk_title_override is None:
  52.         ascii_title = md_iface.getDiscTitle()
  53.         wchar_title = md_iface.getDiscTitle(True).decode('shift_jis')
  54.         disc_title = wchar_title or ascii_title
  55.     else:
  56.         disc_title = disk_title_override
  57.     if disc_title == '':
  58.         directory = '.'
  59.     else:
  60.         directory = disc_title;
  61.     print 'Storing in ', directory
  62.     if not os.path.exists(directory):
  63.         os.mkdir(directory)
  64.     for track, (hour, minute, second, sample), channels, title in \
  65.         getTrackList(md_iface, track_range):
  66.  
  67.         duration = '%02i:%02i:%02i.%03i' % (hour, minute, second, sample/.512)
  68.         filename = '%02i - %s.%s' % (track + 1, title, ext)
  69.         print 'Recording', filename, '(', duration, ')'
  70.         md_iface.gotoTrack(track)
  71.         # Attemp to reduce the MD play delay by...
  72.         print 'Waiting for MD...'
  73.         # ...starting to play (some devices start their seek at this
  74.         # time, others already at gotoTrack)...
  75.         md_iface.play()
  76.         # ... wait until playing really begins ... (waits until the second
  77.         # second of audio playing)
  78.         while md_iface.getPosition()[0:4] != [track, 0, 0, 1]:
  79.             print md_iface.getPosition()
  80.             sleep(0.25)
  81.         # ... pause and go back to track beginning.
  82.         md_iface.pause()
  83.         md_iface.gotoTrack(track)
  84.         if platform.system() == 'Windows':
  85.             sox = 'sox.exe'
  86.         else:
  87.             sox = 'sox'
  88.         start_sox = [sox,
  89.                     '-b','24','-r','96k',
  90.                     '-d',
  91.                     '-S',
  92.                     '-c', channels,
  93.                     '%s/%s' % (directory, filename),
  94.                     'silence', '1', '0.1', '0.1%',
  95.                     'trim', '0', duration,
  96.                     ]
  97.         pid = subprocess.Popen(start_sox)
  98.         md_iface.play()
  99.         sleep(((hour * 60 + minute) * 60) + second)
  100.         while md_iface.getPosition()[0] == track:
  101.             sleep(1)
  102.         md_iface.pause()
  103.         print 'Done, waiting for sox to return...'
  104.         pid.wait()
  105.     # TODO: generate playlists based on groups defined on the MD
  106.     print 'Finished.'
  107.  
  108. if __name__ == '__main__':
  109.     from optparse import OptionParser
  110.     parser = OptionParser()
  111.     parser.add_option('-b', '--bus')
  112.     parser.add_option('-d', '--device')
  113.     parser.add_option('-t', '--track-range')
  114.     parser.add_option('-T', '--title')
  115.     (options, args) = parser.parse_args()
  116.     assert len(args) < 2
  117.     if len(args) == 1:
  118.         ext = args[0]
  119.     else:
  120.         ext = 'ogg'
  121.     track_range = options.track_range
  122.     if track_range is not None:
  123.         if '-' in track_range:
  124.             begin, end = track_range.split('-', 1)
  125.             if begin == '':
  126.                 begin = 0
  127.             else:
  128.                 begin = int(begin) - 1
  129.             if end == '':
  130.                 end = None
  131.             else:
  132.                 end = int(end) - 1
  133.                 assert begin < end
  134.             track_range = (begin, end)
  135.         else:
  136.             track_range = int(track_range) - 1
  137.     main(bus=options.bus, device_address=options.device, ext=ext,
  138.          track_range=track_range, title=options.title)
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top