/* * This file is part of AirReceiver. * * AirReceiver is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * AirReceiver is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with AirReceiver. If not, see <http://www.gnu.org/licenses/>. */ package org.dyndns.jkiddo.raop.server.audio; /** * Describes the layout of the samples in a buffer. * <p> * Serves as a factory for {@link SampleIndexer} instances which provide methods to convert separate channel and sample indices into a combined sample index. */ public enum SampleBufferLayout { Interleaved { @Override public final SampleIndexer getIndexer(final SampleDimensions bufferDimensions, final SampleRange indexedRange) { return new SampleIndexer() { @Override public int getSampleIndex(final int channel, final int sample) { return (indexedRange.offset.sample + sample) * bufferDimensions.channels + indexedRange.offset.channel + channel; } @Override public SampleDimensions getDimensions() { return indexedRange.size; } @Override public SampleIndexer slice(SampleOffset offset, SampleDimensions dimensions) { return getIndexer(bufferDimensions, indexedRange.slice(offset, dimensions)); } @Override public SampleIndexer slice(SampleRange range) { return getIndexer(bufferDimensions, indexedRange.slice(range)); } }; } }, Banded { @Override public final SampleIndexer getIndexer(final SampleDimensions bufferDimensions, final SampleRange indexedRange) { return new SampleIndexer() { @Override public int getSampleIndex(final int channel, final int sample) { return (indexedRange.offset.channel + channel) * bufferDimensions.samples + indexedRange.offset.sample + sample; } @Override public SampleDimensions getDimensions() { return indexedRange.size; } @Override public SampleIndexer slice(SampleOffset offset, SampleDimensions dimensions) { return getIndexer(bufferDimensions, indexedRange.slice(offset, dimensions)); } @Override public SampleIndexer slice(SampleRange range) { return getIndexer(bufferDimensions, indexedRange.slice(range)); } }; } }; /** * Returns a {@link SampleIndexer} which indices the sample in the given {@code indexedRange} inside a buffer with the given {@code bufferDimensions}. * * @param bufferDimensions * The buffer's dimensions * @param indexedRange * The range to index * @return Instance of {@link SampleIndexer} */ public abstract SampleIndexer getIndexer(SampleDimensions bufferDimensions, SampleRange indexedRange); /** * Returns a {@link SampleIndexer} which indices the sample inside a buffer with the given {@code bufferDimensions}. * * @param bufferDimensions * The buffer's dimensions * @return Instance of {@link SampleIndexer} */ public final SampleIndexer getIndexer(final SampleDimensions dims) { return getIndexer(dims, new SampleRange(SampleOffset.Zero, dims)); } /** * Returns a {@link SampleIndexer} which indices the sample inside a buffer with the given {@code bufferDimensions} starting at {@code offset} * * @param bufferDimensions * The buffer's dimensions * @param offset * The offset at which the indices start * @return Instance of {@link SampleIndexer} */ public final SampleIndexer getIndexer(final SampleDimensions dims, final SampleOffset offset) { dims.assertContains(offset); return getIndexer(dims, new SampleRange(offset, dims.reduce(offset.channel, offset.sample))); } }