# API documentation

`AlignedSpans.AlignedSpan`

— Type`AlignedSpan(sample_rate::Number, first_index::Int, last_index::Int)`

Construct an `AlignedSpan`

directly from a `sample_rate`

and indices.

`AlignedSpans.SpanRoundingMode`

— Type`SpanRoundingMode(start::RoundingMode, stop::RoundingMode)`

Creates a rounding object for `AlignedSpan`

to indicate how the `AlignedSpan`

's endpoints should be determined from a given `span`

s endpoints'.

`AlignedSpans.RoundInward`

— Constant`RoundInward = SpanRoundingMode(RoundUp, RoundDown)`

This is a rounding mode where both ends of the continuous time interval are rounded "inwards" to construct the largest span of indices such that all samples are entirely contained within it.

**Example**

Consider a signal with sample rate 1 Hz.

```
Index 1 2 3 4 5
Time (s) 0 1 2 3 4
```

Now, consider the time span 1.5s (inclusive) to 2.5s (exclusive). Using brackets to highlight this span:

```
Index 1 2 3 4 5
Time (s) 0 1 [ 2 ) 3 4
```

In code, this span is described by

```
julia> using AlignedSpans, Dates, TimeSpans
julia> ts = TimeSpan(Millisecond(1500), Millisecond(2500))
TimeSpan(00:00:01.500000000, 00:00:02.500000000)
```

The only sample within the span is at index 3. And indeed,

```
julia> aligned = AlignedSpan(1, ts, RoundInward)
AlignedSpan(1.0, 3, 3)
julia> AlignedSpans.indices(aligned)
3:3
```

gives an `AlignedSpan`

with indices `3:3`

.

`AlignedSpans.RoundSpanDown`

— Constant`RoundSpanDown = SpanRoundingMode(RoundDown, RoundDown)`

This is a rounding mode where *both* ends of the continuous time interval are rounded downwards.

**Example**

Consider a signal with sample rate 1 Hz.

```
Index 1 2 3 4 5
Time (s) 0 1 2 3 4
```

Now, consider the time span 1.5s (inclusive) to 2.5s (exclusive). Using brackets to highlight this span:

```
Index 1 2 3 4 5
Time (s) 0 1 [ 2 ) 3 4
```

In code, this span is described by

```
julia> using AlignedSpans, Dates, TimeSpans
julia> ts = TimeSpan(Millisecond(1500), Millisecond(2500))
TimeSpan(00:00:01.500000000, 00:00:02.500000000)
```

If we round both ends of the interval down to the nearest sample, the start of the interval becomes 1s, and the stop of the interval becomes 2s. Thus, the associated samples are at indices `2:3`

. And indeed,

```
julia> aligned = AlignedSpan(1, ts, RoundSpanDown)
AlignedSpan(1.0, 2, 3)
julia> AlignedSpans.indices(aligned)
2:3
```

gives an `AlignedSpan`

with indices `2:3`

.

`AlignedSpans.AlignedSpan`

— Method`AlignedSpan(sample_rate, span, mode::SpanRoundingMode)`

Creates an `AlignedSpan`

by rounding the left endpoint according to `mode.start`

, and the right endpoint by `mode.stop`

.

If `mode.start==RoundUp`

, then the left index of the resulting span is guaranteed to be inside `span`

. This is accomplished by checking if the left endpoint of the span is exclusive, and if so, incrementing the index after rounding when necessary.

Likewise, if `mode.start==RoundDown`

, then the right index of the resulting span is guaranteed to be inside `span`

. This is accomplished by checking if the right endpoint of the span is exclusive, and if so, decrementing the index after rounding when necessary.

Note: `span`

may be of any type which which provides methods for `AlignedSpans.start_index_from_time`

and `AlignedSpans.stop_index_from_time`

.

`AlignedSpans.ConstantSamplesRoundingMode`

— Type`ConstantSamplesRoundingMode(start::RoundingMode)`

Creates a rounding object for `AlignedSpan`

to indicate the `AlignedSpan`

should be constructed by the `start`

and `duration`

of the `span`

, without regard to its `stop`

.

If two `span`

s have the same duration, then the resulting `AlignedSpan`

's will have the same number of samples when constructed with this rounding mode.

See also `AlignedSpan(sample_rate, span, mode::ConstantSamplesRoundingMode)`

.

`AlignedSpans.AlignedSpan`

— Method`AlignedSpan(sample_rate, span, mode::ConstantSamplesRoundingMode)`

Creates an `AlignedSpan`

whose left endpoint is rounded according to `mode.start`

, and whose right endpoint is determined so by the left endpoint and the number of samples, given by `AlignedSpans.n_samples(sample_rate, duration(span))`

.

Interface: `span`

may be of any type which which provides a method for `AlignedSpans.start_index_from_time`

and `TimeSpans.duration`

.

**More detailed information**

This is designed so that if `AlignedSpan(sample_rate, span, mode::ConstantSamplesRoundingMode)`

is applied to multiple `span`

s, with the same `sample_rate`

, and the same durations, then the resulting `AlignedSpan`

's will have the same number of samples.

For this reason, we ask for `TimeSpans.duration(span)`

to be defined, rather than a `n_samples(span)`

function: the idea is that we want to only using the duration and the starting time, rather than the *actual* number of samples in this particular `span`

.

In contrast, `AlignedSpan(sample_rate, span, RoundInward)`

provides an `AlignedSpan`

which includes only (and exactly) the samples contained within `span`

.

If one wants to create a collection of consecutive, non-overlapping, `AlignedSpans`

each with the same number of samples, then use `consecutive_subspans`

instead.

`AlignedSpans.consecutive_subspans`

— Function```
consecutive_subspans(span::AlignedSpan, duration::Period; keep_last=true)
consecutive_subspans(span::AlignedSpan, n_window_samples::Int; keep_last=true)
```

Creates an iterator of `AlignedSpan`

such that each `AlignedSpan`

has consecutive indices which cover the original `span`

's indices (when `keep_last=true`

).

If `keep_last=true`

(the default behavior), then the last span may have fewer samples than the others, and

- Each span has
`n_window_samples`

samples (which is calculated as`n_samples(span.sample_rate, duration)`

if`duration::Period`

is supplied), except possibly

the last one, which may have fewer.

- The number of subspans is given by
`cld(n_samples(span), n_window_samples)`

, - The number of samples in the last subspan is
`r = rem(n_samples(span), n_window_samples)`

unless`r=0`

, in which

case the the last subspan has the same number of samples as the rest, namely `n_window_samples`

.

- All of the indices of
`span`

are guaranteed to be covered by exactly one subspan

If `keep_last=false`

, then all spans will have the same number of samples:

- Each span has
`n_window_samples`

samples (which is calculated as`n_samples(span.sample_rate, duration)`

if`duration::Period`

is supplied) - The number of subspans is given by
`fld(n_samples(span), n_window_samples)`

- The last part of the
`span`

's indices may not be covered (when we can't fit in another subspan of length`n_window_samples`

)

`AlignedSpans.consecutive_overlapping_subspans`

— Function```
consecutive_overlapping_subspans(span::AlignedSpan, duration::Period,
hop_duration::Period)
consecutive_overlapping_subspans(span::AlignedSpan, n_window_samples::Int, n_hop_samples::Int)
```

Create an iterator of `AlignedSpan`

such that each `AlignedSpan`

has `n_window_samples`

(calculated as `n_samples(span.sample_rate, duration)`

if `duration::Period`

is supplied) samples, shifted by `n_hop_samples`

(calculated as `n_samples(span.sample_rate, hop_duration)`

if `hop_duration::Period`

is supplied) samples between consecutive spans.

When `n_samples(span)`

is not an integer multiple of `n_window_samples`

, only AlignedSpans with `n_window_samples`

samples will be returned. This is analgous to `consecutive_subspans`

with `keep_last=false`

, which is not the default behavior for `consecutive_subspans`

.

Note: If `hop_duration`

cannot be represented as an integer number of samples, rounding will occur to ensure that all output AlignedSpans will have the same number of samples. When rounding occurs, the output `hop_duration`

will be: `Nanosecond(n_samples(samp_rate, hop_duration) / samp_rate * 1e9)`

`AlignedSpans.n_samples`

— Function`n_samples(sample_rate, duration::Union{Period, Dates.CompoundPeriod})`

Returns the minimal number of samples that can occur in a span of `duration`

.

`n_samples(aligned::AlignedSpan)`

Returns the number of samples present in the span `aligned`

.

`AlignedSpans.indices`

— Function`AlignedSpans.indices(span::AlignedSpan) -> UnitRange{Int64}`

Returns the sample indices associated to an `AlignedSpan`

.

## Interface for conversion from continuous time spans

In order to support conversion of continuous time `span`

types to `AlignedSpan`

's, three methods may be defined. These are not exported, because they are generally not used directly, but rather defined in order to facilitate use of the `AlignedSpan`

constructors.

`AlignedSpans.start_index_from_time`

— Function`AlignedSpans.start_index_from_time(sample_rate, span, rounding_mode)`

Returns the index of a sample object obtained by rounding the start of `span`

according to `rounding_mode`

.

See also `AlignedSpan(sample_rate, span, mode::SpanRoundingMode)`

and `AlignedSpan(sample_rate, span, mode::ConstantSamplesRoundingMode)`

.

`AlignedSpans.stop_index_from_time`

— Function`AlignedSpans.stop_index_from_time(sample_rate, span, rounding_mode)`

Returns the index of a sample object obtained by rounding the stop of `span`

according to `rounding_mode`

.

See also `AlignedSpan(sample_rate, span, mode::SpanRoundingMode)`

.