001/* A simple application that demonstrates the use of LiveSound by performing 002 simple additive synthesis in real-time. 003 004 Copyright (c) 2000-2014 The Regents of the University of California. 005 All rights reserved. 006 Permission is hereby granted, without written agreement and without 007 license or royalty fees, to use, copy, modify, and distribute this 008 software and its documentation for any purpose, provided that the above 009 copyright notice and the following two paragraphs appear in all copies 010 of this software. 011 012 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 013 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 014 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 015 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 016 SUCH DAMAGE. 017 018 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 019 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 020 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 021 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 022 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 023 ENHANCEMENTS, OR MODIFICATIONS. 024 025 PT_COPYRIGHT_VERSION_2 026 COPYRIGHTENDKEY 027 028 */ 029package ptolemy.media.javasound.demo.LiveSines; 030 031import java.io.IOException; 032 033import ptolemy.actor.injection.ActorModuleInitializer; 034import ptolemy.media.javasound.LiveSound; 035 036//////////////////////////////////////////////////// 037 038/** 039 A simple application that demonstrates the use of LiveSound. This 040 application synthesizes and plays a simple harmonic signal, using simple 041 additive synthesis. The signal is the sum of a few harmonically related 042 sinusoids. 043 044 @author Brian K. Vogel, Neil E. Turner 045 @version $Id$ 046 @since Ptolemy II 3.1 047 @Pt.ProposedRating Red (vogel) 048 @Pt.AcceptedRating Red (vogel) 049 */ 050public class LiveSines { 051 /** Play a simple harmonic signal. 052 * @param args Ignored. 053 */ 054 public static void main(String[] args) { 055 ActorModuleInitializer.initializeInjector(); 056 057 // The pitch of the signal to synthesize. 058 double fundamental1_Hz = 220; 059 060 // The pitch of the signal to synthesize. 061 double fundamental2_Hz = 220 * 1.5; 062 063 int sampleRate = 44100; // in Hz 064 int sampleSizeInBits = 16; 065 int channels = 2; // stereo. 066 int outBufferSize = 4096; // Internal buffer size for playback. 067 068 // Amount of data to read or write from/to the internal buffer 069 // at a time. This should be set smaller than the internal buffer 070 // size! 071 int putSamplesSize = 25; 072 073 try { 074 LiveSound.setSampleRate(sampleRate); 075 LiveSound.setChannels(channels); 076 System.out.println("Attempting to set playback buffer size: " 077 + outBufferSize + " samples."); 078 LiveSound.setBufferSize(outBufferSize); 079 LiveSound.setBitsPerSample(sampleSizeInBits); 080 LiveSound.setTransferSize(putSamplesSize); 081 082 // Begin playback. 083 LiveSound.startPlayback(_producer); 084 } catch (IOException ex) { 085 System.err.println(ex); 086 } 087 088 double[][] samplesArray = new double[channels][putSamplesSize]; 089 090 // keep track of time, used in calculating the sine wave values. 091 double[] samples = new double[channels]; 092 093 System.out.println(" Actual size: " 094 + LiveSound.getBufferSizePlayback() + " samples."); 095 096 try { 097 int channelNumber; 098 099 // Loop forever. 100 while (true) { 101 for (int i = 0; i < putSamplesSize; i++) { 102 channelNumber = 0; //Left channel. 103 104 // Generate a harmonic signal. 105 samplesArray[channelNumber][i] = Math 106 .sin(fundamental1_Hz * 2 * Math.PI 107 * samples[channelNumber]) 108 * 0.1 109 + Math.sin(2 * fundamental1_Hz * 2 * Math.PI 110 * samples[channelNumber]) * 0.3 111 + Math.sin(3 * fundamental1_Hz * 2 * Math.PI 112 * samples[channelNumber]) * 0.3 113 + Math.sin(4 * fundamental1_Hz * 2 * Math.PI 114 * samples[channelNumber]) * 0.2; 115 116 // Increment time for the signal on this channel. 117 samples[channelNumber] = samples[channelNumber] 118 + 1.0 / sampleRate; 119 120 channelNumber = 1; //Right channel. 121 122 // Generate a harmonic signal. 123 samplesArray[channelNumber][i] = Math 124 .sin(fundamental2_Hz * 2 * Math.PI 125 * samples[channelNumber]) 126 * 0.4 127 + Math.sin(2 * fundamental2_Hz * 2 * Math.PI 128 * samples[channelNumber]) * 0.3 129 + Math.sin(3 * fundamental2_Hz * 2 * Math.PI 130 * samples[channelNumber]) * 0.25 131 + Math.sin(4 * fundamental2_Hz * 2 * Math.PI 132 * samples[channelNumber]) * 0.2; 133 134 // Increment time for the signal on this channel. 135 samples[channelNumber] = samples[channelNumber] 136 + 1.0 / sampleRate; 137 } 138 139 // Play the processed audio samples. 140 LiveSound.putSamples(_producer, samplesArray); 141 142 // break out of loop after 10 seconds. 0 is the channel number 143 // chosen arbitrarily 144 if (samples[0] > 10.0) { 145 break; 146 } 147 } 148 149 LiveSound.stopPlayback(_producer); 150 } catch (Throwable throwable) { 151 System.err.println(throwable); 152 } 153 } 154 155 private static Object _producer = new Object(); 156}