punk@44: // The MIT License
punk@44: 
punk@44: // Copyright (c) 2009 Massachusetts Institute of Technology
punk@44: 
punk@44: // Permission is hereby granted, free of charge, to any person obtaining a copy
punk@44: // of this software and associated documentation files (the "Software"), to deal
punk@44: // in the Software without restriction, including without limitation the rights
punk@44: // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
punk@44: // copies of the Software, and to permit persons to whom the Software is
punk@44: // furnished to do so, subject to the following conditions:
punk@44: 
punk@44: // The above copyright notice and this permission notice shall be included in
punk@44: // all copies or substantial portions of the Software.
punk@44: 
punk@44: // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
punk@44: // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
punk@44: // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
punk@44: // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
punk@44: // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
punk@44: // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
punk@44: // THE SOFTWARE.
punk@44: 
punk@44: import Connectable::*;
punk@44: import GetPut::*;
punk@44: import ClientServer::*;
punk@44: import Vector::*;
punk@44: import FIFO::*;
punk@44: import FixedPoint::*;
punk@44: 
punk@44: //AWB includes
punk@44: `include "asim/provides/low_level_platform_interface.bsh"
punk@44: `include "asim/provides/soft_connections.bsh"
punk@44: `include "asim/provides/common_services.bsh"
punk@44: 
punk@44: // Local includes
punk@44: `include "asim/provides/audio_pipe_types.bsh"
punk@44: `include "asim/provides/path_types.bsh"
punk@44: 
punk@44: interface Mixer;
punk@53:    method Action toMixer(AudioStream streamIn);
punk@53:    interface Get#(AudioProcessorUnit) mainOut;
punk@44: endinterface
punk@44: 
punk@53: module [CONNECTED_MODULE]  mkMixer#(Integer numVoices, Vector#(numVoices, Volume) scalars) (Mixer);
punk@44: 
punk@53:    function Bool isAudioFini(Vector#(numVoices, Reg#(Bool)) voiceStat);
punk@53:      Bool result = True;
punk@53:       for (Integer i = 0; i < numVoices; i = i+1)
punk@53:         begin
punk@53:           result = voiceStat[i] && result;
punk@53:         end
punk@53:      return result; 
punk@53:    endfunction
punk@44: 
punk@44: 	 
punk@44:   // Instantiate the modules
punk@53:    Vector#(numVoices, FIFO#(AudioPipeUnit)) voicesIn <- replicateM(mkFIFO());
punk@44: // <- newVector();
punk@53:    Vector#(numVoices, Reg#(Bool)) voiceFini <- replicateM(mkReg(False));
punk@44: 
punk@44:    FIFO#(AudioProcessorUnit) masterFifo <- mkFIFO();
punk@44: 
punk@44:    rule sendEnd(isAudioFini(voiceFini));
punk@44:       masterFifo.enq(tagged EndOfFile);
punk@44:       //prep for reset
punk@53:       for (Integer i = 0; i < numVoices; i = i+1)
punk@44: 	 voiceFini[i] <= False;
punk@44:    endrule
punk@44:    
punk@44:    rule processSample(!isAudioFini(voiceFini));  //implicit on all voiceFifos having data
punk@44:       FixedPoint#(32,32) sum = 0;  //this should allow 16 voices at 16 bits without messing up
punk@68:       Integer numValid = 0;
punk@53:       for (Integer i = 0; i < numVoices; i = i+1)
punk@44: 	 begin
punk@44: 	    if (voicesIn[i].first() matches tagged Valid .data)
punk@44: 	      begin
punk@44: 		 case (data) matches
punk@44: 		    tagged Sample .sample :
punk@68: 		       begin //shifting right 8 to divide by 256
punk@68: 			  sum = sum + ((fromInt(sample) * fromInt(scalars[i])) >> 8); 
punk@68: 			  numValid = numValid + 1;
punk@68: 		       end
punk@44: 		    tagged EndOfFile :
punk@44: 		       voiceFini[i] <= True;
punk@44: 		 endcase
punk@44: 	      end
punk@44: 	    else voiceFini[i] <= True;
punk@44: 	    voicesIn[i].deq();
punk@44: 	 end
punk@68:        if (numValid > 0)  // If nothing is valid, don't send anything
punk@68: 	  masterFifo.enq(tagged Sample truncate(fxptGetInt(sum >> numVoices)));
punk@44:    endrule
punk@44:  
punk@44:   // Internal connections
punk@44: 
punk@53:    method Action toMixer(AudioStream streamIn);
punk@53: 	 voicesIn[streamIn.voice].enq(streamIn.data);
punk@53:    endmethod
punk@53:    
punk@53:    interface Get mainOut = fifoToGet(masterFifo);
punk@44: 
punk@44: endmodule