001package org.intellimate.izou.system.sound; 002 003import org.intellimate.izou.addon.AddOnModel; 004import org.intellimate.izou.main.Main; 005 006import javax.sound.sampled.AudioFormat; 007import javax.sound.sampled.LineUnavailableException; 008import javax.sound.sampled.SourceDataLine; 009 010/** 011 * the delegation to SourceDataLine. 012 * @author LeanderK 013 * @version 1.0 014 */ 015public class IzouSoundSourceDataLine extends IzouSoundDataLine implements SourceDataLine { 016 private final SourceDataLine sourceDataLine; 017 018 public IzouSoundSourceDataLine(SourceDataLine dataLine, Main main, boolean isPermanent, AddOnModel addOnModel) { 019 super(dataLine, main, isPermanent, addOnModel); 020 this.sourceDataLine = dataLine; 021 } 022 023 /** 024 * Opens the line with the specified format and suggested buffer size, 025 * causing the line to acquire any required 026 * system resources and become operational. 027 * <p> 028 * The buffer size is specified in bytes, but must represent an integral 029 * number of sample frames. Invoking this method with a requested buffer 030 * size that does not meet this requirement may result in an 031 * IllegalArgumentException. The actual buffer size for the open line may 032 * differ from the requested buffer size. The value actually set may be 033 * queried by subsequently calling <code>DataLine#getBufferSize</code>. 034 * <p> 035 * If this operation succeeds, the line is marked as open, and an 036 * <code>LineEvent.Type#OPEN OPEN</code> event is dispatched to the 037 * line's listeners. 038 * <p> 039 * Invoking this method on a line which is already open is illegal 040 * and may result in an <code>IllegalStateException</code>. 041 * <p> 042 * Note that some lines, once closed, cannot be reopened. Attempts 043 * to reopen such a line will always result in a 044 * <code>LineUnavailableException</code>. 045 * 046 * @param format the desired audio format 047 * @param bufferSize the desired buffer size 048 * @throws LineUnavailableException if the line cannot be 049 * opened due to resource restrictions 050 * @throws IllegalArgumentException if the buffer size does not represent 051 * an integral number of sample frames, 052 * or if <code>format</code> is not fully specified or invalid 053 * @throws IllegalStateException if the line is already open 054 * @throws SecurityException if the line cannot be 055 * opened due to security restrictions 056 * 057 * @see #open(AudioFormat) 058 */ 059 @Override 060 public void open(AudioFormat format, int bufferSize) throws LineUnavailableException { 061 opening(); 062 sourceDataLine.open(format, bufferSize); 063 } 064 065 /** 066 * Opens the line with the specified format, causing the line to acquire any 067 * required system resources and become operational. 068 * 069 * <p> 070 * The implementation chooses a buffer size, which is measured in bytes but 071 * which encompasses an integral number of sample frames. The buffer size 072 * that the system has chosen may be queried by subsequently calling 073 * <code>DataLine#getBufferSize</code>. 074 * <p> 075 * If this operation succeeds, the line is marked as open, and an 076 * <code>LineEvent.Type#OPEN OPEN</code> event is dispatched to the 077 * line's listeners. 078 * <p> 079 * Invoking this method on a line which is already open is illegal 080 * and may result in an <code>IllegalStateException</code>. 081 * <p> 082 * Note that some lines, once closed, cannot be reopened. Attempts 083 * to reopen such a line will always result in a 084 * <code>LineUnavailableException</code>. 085 * 086 * @param format the desired audio format 087 * @throws LineUnavailableException if the line cannot be 088 * opened due to resource restrictions 089 * @throws IllegalArgumentException if <code>format</code> 090 * is not fully specified or invalid 091 * @throws IllegalStateException if the line is already open 092 * @throws SecurityException if the line cannot be 093 * opened due to security restrictions 094 * 095 * @see #open(AudioFormat, int) 096 */ 097 @Override 098 public void open(AudioFormat format) throws LineUnavailableException { 099 opening(); 100 sourceDataLine.open(format); 101 } 102 103 /** 104 * Writes audio data to the mixer via this source data line. The requested 105 * number of bytes of data are read from the specified array, 106 * starting at the given offset into the array, and written to the data 107 * line's buffer. If the caller attempts to write more data than can 108 * currently be written (see <code>DataLine#available available</code>), 109 * this method blocks until the requested amount of data has been written. 110 * This applies even if the requested amount of data to write is greater 111 * than the data line's buffer size. However, if the data line is closed, 112 * stopped, or flushed before the requested amount has been written, 113 * the method no longer blocks, but returns the number of bytes 114 * written thus far. 115 * <p> 116 * The number of bytes that can be written without blocking can be ascertained 117 * using the <code>DataLine#available available</code> method of the 118 * <code>DataLine</code> interface. (While it is guaranteed that 119 * this number of bytes can be written without blocking, there is no guarantee 120 * that attempts to write additional data will block.) 121 * <p> 122 * The number of bytes to write must represent an integral number of 123 * sample frames, such that: 124 * <br> 125 * <center><code>[ bytes written ] % [frame size in bytes ] == 0</code></center> 126 * <br> 127 * The return value will always meet this requirement. A request to write a 128 * number of bytes representing a non-integral number of sample frames cannot 129 * be fulfilled and may result in an <code>IllegalArgumentException</code>. 130 * 131 * @param b a byte array containing data to be written to the data line 132 * @param off the offset from the beginning of the array, in bytes 133 * @param len the length, in bytes, of the valid data in the array 134 * (in other words, the requested amount of data to write, in bytes) 135 * @return the number of bytes actually written 136 * @throws IllegalArgumentException if the requested number of bytes does 137 * not represent an integral number of sample frames, 138 * or if <code>len</code> is negative 139 * @throws ArrayIndexOutOfBoundsException if <code>off</code> is negative, 140 * or <code>off+len</code> is greater than the length of the array 141 * <code>b</code>. 142 */ 143 @Override 144 public int write(byte[] b, int off, int len) { 145 if (isMutable) { 146 return sourceDataLine.write(b, off, len); 147 } else { 148 if (isMutedFromSystem) { 149 byte[] newArr = new byte[b.length]; 150 return sourceDataLine.write(newArr, off, len); 151 } else { 152 return sourceDataLine.write(b, off, len); 153 } 154 } 155 } 156}