/* * ***************************************************************************** * Copyright (C) 2014-2023 Dennis Sheirer * * This program 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. * * This program 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 this program. If not, see * **************************************************************************** */ package io.github.dsheirer.buffer; import io.github.dsheirer.sample.complex.ComplexSamples; import io.github.dsheirer.sample.complex.InterleavedComplexSamples; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; /** * Native buffer wrapper that lets multiple channels share one conversion of the native samples. Each channel's * iterator returns the same complex samples instances, on the channel's own thread, so consumers must not modify the * samples. The converted samples are released when the channels release this wrapper. */ public class SharedNativeBuffer implements INativeBuffer { private final INativeBuffer mNativeBuffer; private final List mConverted = new ArrayList<>(); private Iterator mConverter; /** * Constructs an instance * @param nativeBuffer to convert */ public SharedNativeBuffer(INativeBuffer nativeBuffer) { mNativeBuffer = nativeBuffer; } /** * Indicates if the converted samples include the index, converting the next samples as needed. */ private synchronized boolean hasConverted(int index) { if(mConverter == null) { mConverter = mNativeBuffer.iterator(); } if(index == mConverted.size() && mConverter.hasNext()) { mConverted.add(mConverter.next()); } return index < mConverted.size(); } private synchronized ComplexSamples getConverted(int index) { return mConverted.get(index); } @Override public Iterator iterator() { return new Iterator<>() { private int mIndex = 0; @Override public boolean hasNext() { return hasConverted(mIndex); } @Override public ComplexSamples next() { if(!hasNext()) { throw new NoSuchElementException("No more samples"); } return getConverted(mIndex++); } }; } @Override public Iterator iteratorInterleaved() { return mNativeBuffer.iteratorInterleaved(); } @Override public int sampleCount() { return mNativeBuffer.sampleCount(); } @Override public long getTimestamp() { return mNativeBuffer.getTimestamp(); } }