view src/samer/audio/AudioSource.java @ 8:5e3cbbf173aa tip

Reorganise some more
author samer
date Fri, 05 Apr 2019 22:41:58 +0100
parents 5df24c91468d
children
line wrap: on
line source
/*
 *	AudioSource.java	
 *
 *	Copyright (c) 2000, Samer Abdallah, King's College London.
 *	All rights reserved.
 *
 *	This software is provided AS iS and WITHOUT ANY WARRANTY; 
 *	without even the implied warranty of MERCHANTABILITY or 
 *	FITNESS FOR A PARTICULAR PURPOSE.
 */

package samer.audio;
import samer.tools.*;

/**
	General interface for objects that can supply an
	audio stream.
*/

public interface AudioSource
{
	boolean  isOpen();
	void open() throws Exception;
	void close();
	void dispose();

	/** return a task which reads samples into the given buffer
	 *  The idea is that the audio source can choose the right
	 *  kind of reader depending on the format of the audio stream,
	 *  and then handle the conversion to doubles automatically
	 */
	Task reader(double buf[], int off, int len);
	Task reader(float buf[], int off, int len);

	int getChannels();
	float getRate();

	public static class Util {
		/* NB. These copying functions allow NEGATIVE offset (off<0). The semantics 
		 * of this is are that n values are copied from source to destination, writing 
		 * into the destination starting at the negative offset, but that values before
		 * index 0 will never be accessed, hence, they are not actually copied. Only
		 * the last n-off values will be available in dst starting from index 0.
		 * This is useful as it allows block-wise audio input where the block lenght
		 * is smaller than the step length.
		 */

		public static void shortToDoubleMixDown(byte [] src, double [] dst, int off, int n, int m) {
			double a = (1.0/(m*32768.0)); // scaling factor including division by mixdown factor m
			int skip = off<0 ? -off : 0;
			for (int i=2*m*skip, j=off+skip; j<n+off; j++) {
				dst[j] = 0;
				for (int k=0; k<m; k++) dst[j] += a*((src[i++]&0xff) | src[i++]<<8);
			}
		}

		public static void mediumToDouble(byte [] src, double [] dst, int off, int n) {
			int i, j;
			if (off<0) { i= 3*(-off); j=0; } else { i=0; j=off; }
			while (j<n+off) dst[j++] = (1.0/8388608.0)*((src[i++]&0xff) | src[i++]<<8 | src[i++]<<16);
		}

		public static void shortToDouble(byte [] src, double [] dst, int off, int n) {
			int i, j;
			if (off<0) { i= 2*(-off); j=0; } else { i=0; j=off; }
			while (j<n+off) dst[j++] = (1.0/32768.0)*((src[i++]&0xff) | src[i++]<<8);
		}

		public static void byteToDouble(byte [] src, double [] dst, int off, int n) {
			int i, j;
			if (off<0) { i= -off; j=0; } else { i=0; j=off; }
			while (j<n+off) dst[j++] = (1.0/256.0)*(src[i++]&0xff)-128.0;
		}

		public static void shortToFloatMixDown(byte [] src, float [] dst, int off, int n, int m) {
			int skip = off<0 ? -off : 0;
			float a = (1F/(m*32768F)); // scaling factor including division by mixdown factor m
			for (int i=2*m*skip, j=off+skip; j<n+off; j++) {
				dst[j] = 0;
				for (int k=0; k<m; k++) dst[j] += a*((src[i++]&0xff) | src[i++]<<8);
			}
		}

		public static void shortToFloat(byte [] src, float [] dst, int off, int n) {
			int i, j;
			if (off<0) { i= -2*off; j=0; } else { i=0; j=off; }
			while (j<n+off) dst[j++] = (1F/32768F)*((src[i++]&0xff) | src[i++]<<8);
		}

		public static void byteToFloat(byte [] src, float [] dst, int off, int n) {
			int i, j;
			if (off<0) { i= -off; j=0; } else { i=0; j=off; }
			while (j<n+off) dst[j++] = (1F/256F)*(src[i++]&0xff)-128F;
		}
	}
}