Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • python/lib/aubio/slicing.py

    rdc654f8 r2c8ada6  
    66_max_timestamp = 1e120
    77
     8
    89def slice_source_at_stamps(source_file, timestamps, timestamps_end=None,
    9                            output_dir=None, samplerate=0, hopsize=256):
    10     """ slice a sound file at given timestamps """
     10                           output_dir=None, samplerate=0, hopsize=256,
     11                           create_first=False):
     12    """Slice a sound file at given timestamps.
    1113
    12     if timestamps is None or len(timestamps) == 0:
     14    This function reads `source_file` and creates slices, new smaller
     15    files each starting at `t` in `timestamps`, a list of integer
     16    corresponding to time locations in `source_file`, in samples.
     17
     18    If `timestamps_end` is unspecified, the slices will end at
     19    `timestamps_end[n] = timestamps[n+1]-1`, or the end of file.
     20    Otherwise, `timestamps_end` should be a list with the same length
     21    as `timestamps` containing the locations of the end of each slice.
     22
     23    If `output_dir` is unspecified, the new slices will be written in
     24    the current directory. If `output_dir` is a string, new slices
     25    will be written in `output_dir`, after creating the directory if
     26    required.
     27
     28    The default `samplerate` is 0, meaning the original sampling rate
     29    of `source_file` will be used. When using a sampling rate
     30    different to the one of the original files, `timestamps` and
     31    `timestamps_end` should be expressed in the re-sampled signal.
     32
     33    The `hopsize` parameter simply tells :class:`source` to use this
     34    hopsize and does not change the output slices.
     35
     36    If `create_first` is True and `timestamps` does not start with `0`, the
     37    first slice from `0` to `timestamps[0] - 1` will be automatically added.
     38
     39    Parameters
     40    ----------
     41    source_file : str
     42        path of the resource to slice
     43    timestamps : :obj:`list` of :obj:`int`
     44        time stamps at which to slice, in samples
     45    timestamps_end : :obj:`list` of :obj:`int` (optional)
     46        time stamps at which to end the slices
     47    output_dir : str (optional)
     48        output directory to write the slices to
     49    samplerate : int (optional)
     50        samplerate to read the file at
     51    hopsize : int (optional)
     52        number of samples read from source per iteration
     53    create_first : bool (optional)
     54        always create the slice at the start of the file
     55
     56    Examples
     57    --------
     58    Create two slices: the first slice starts at the beginning of the
     59    input file `loop.wav` and lasts exactly one second, starting at
     60    sample `0` and ending at sample `44099`; the second slice starts
     61    at sample `44100` and lasts until the end of the input file:
     62
     63    >>> aubio.slice_source_at_stamps('loop.wav', [0, 44100])
     64
     65    Create one slice, from 1 second to 2 seconds:
     66
     67    >>> aubio.slice_source_at_stamps('loop.wav', [44100], [44100 * 2 - 1])
     68
     69    Notes
     70    -----
     71    Slices may be overlapping. If `timestamps_end` is `1` element
     72    shorter than `timestamps`, the last slice will end at the end of
     73    the file.
     74    """
     75
     76    if not timestamps:
    1377        raise ValueError("no timestamps given")
    1478
    15     if timestamps[0] != 0:
     79    if timestamps[0] != 0 and create_first:
    1680        timestamps = [0] + timestamps
    1781        if timestamps_end is not None:
     
    1983
    2084    if timestamps_end is not None:
    21         if len(timestamps_end) != len(timestamps):
     85        if len(timestamps_end) == len(timestamps) - 1:
     86            timestamps_end = timestamps_end + [_max_timestamp]
     87        elif len(timestamps_end) != len(timestamps):
    2288            raise ValueError("len(timestamps_end) != len(timestamps)")
    2389    else:
     
    2591
    2692    regions = list(zip(timestamps, timestamps_end))
    27     #print regions
    2893
    2994    source_base_name, _ = os.path.splitext(os.path.basename(source_file))
     
    3398        source_base_name = os.path.join(output_dir, source_base_name)
    3499
    35     def new_sink_name(source_base_name, timestamp, samplerate):
    36         """ create a sink based on a timestamp in samples, converted in seconds """
     100    def _new_sink_name(source_base_name, timestamp, samplerate):
     101        # create name based on a timestamp in samples, converted in seconds
    37102        timestamp_seconds = timestamp / float(samplerate)
    38103        return source_base_name + "_%011.6f" % timestamp_seconds + '.wav'
     
    49114        vec, read = _source.do_multi()
    50115        # if the total number of frames read will exceed the next region start
    51         if len(regions) and total_frames + read >= regions[0][0]:
    52             #print "getting", regions[0], "at", total_frames
     116        while regions and total_frames + read >= regions[0][0]:
    53117            # get next region
    54118            start_stamp, end_stamp = regions.pop(0)
    55119            # create a name for the sink
    56             new_sink_path = new_sink_name(source_base_name, start_stamp, samplerate)
     120            new_sink_path = _new_sink_name(source_base_name, start_stamp,
     121                                           samplerate)
    57122            # create its sink
    58123            _sink = sink(new_sink_path, samplerate, _source.channels)
    59124            # create a dictionary containing all this
    60             new_slice = {'start_stamp': start_stamp, 'end_stamp': end_stamp, 'sink': _sink}
     125            new_slice = {'start_stamp': start_stamp, 'end_stamp': end_stamp,
     126                         'sink': _sink}
    61127            # append the dictionary to the current list of slices
    62128            slices.append(new_slice)
     
    70136            # number of samples yet to written be until end of region
    71137            remaining = end_stamp - total_frames + 1
    72             #print current_slice, remaining, start
    73138            # not enough frames remaining, time to split
    74139            if remaining < read:
     
    76141                    # write remaining samples from current region
    77142                    _sink.do_multi(vec[:, start:remaining], remaining - start)
    78                     #print "closing region", "remaining", remaining
    79143                    # close this file
    80144                    _sink.close()
     
    83147                _sink.do_multi(vec[:, start:read], read - start)
    84148        total_frames += read
     149        # remove old slices
     150        slices = list(filter(lambda s: s['end_stamp'] > total_frames,
     151                             slices))
    85152        if read < hopsize:
    86153            break
Note: See TracChangeset for help on using the changeset viewer.