Esempio n. 1
0
		/**********************************************************************************************
		 *
		 *  OKIM 6295 ADPCM chip:
		 *
		 *  Command bytes are sent:
		 *
		 *      1xxx xxxx = start of 2-byte command sequence, xxxxxxx is the sample number to trigger
		 *      abcd vvvv = second half of command; one of the abcd bits is set to indicate which voice
		 *                  the v bits seem to be volumed
		 *
		 *      0abc d000 = stop playing; one or more of the abcd bits is set to indicate which voice(s)
		 *
		 *  Status is read:
		 *
		 *      ???? abcd = one bit per voice, set to 0 if nothing is playing, or 1 if it is active
		 *
		***********************************************************************************************/


		/**********************************************************************************************

			 okim6295_update -- update the sound chip so that it is in sync with CPU execution

		***********************************************************************************************/

		//static STREAM_UPDATE( okim6295_update )
		private void okim6295_update(byte ChipID, int[][] outputs, int samples)
		{
			//System.Console.Write("samples:{0}\n"        , samples);
			//okim6295_state *chip = (okim6295_state *)param;
			okim6295_state chip = OKIM6295Data[ChipID];
			int i;

			//memset(outputs[0], 0, samples * sizeof(*outputs[0]));
			for (i = 0; i < samples; i++)
			{
				outputs[0][i] = 0;
			}

			for (i = 0; i < okim6295_state.OKIM6295_VOICES; i++)
			//    for (i = 0; i < 1; i++)
			{
				ADPCMVoice voice = chip.voice[i];
				infos[ChipID].chInfo[i].mask = voice.Muted == 0;
				if (voice.Muted == 0)
				{
					int[][] buffer = outputs;
					int ptrBuffer = 0;
					short[] sample_data = new short[MAX_SAMPLE_CHUNK];
					int remaining = samples;

					/* loop while we have samples remaining */
					while (remaining != 0)
					{
						int Samples = (remaining > MAX_SAMPLE_CHUNK) ? MAX_SAMPLE_CHUNK : remaining;
						int samp;

						generate_adpcm(chip, voice, sample_data, Samples);
						for (samp = 0; samp < Samples; samp++)
						{
							buffer[0][ptrBuffer++] += sample_data[samp];
                            //if (sample_data[samp] != 0)
                            //{
                            //    System.Console.WriteLine("ch:{0} sampledata[{1}]={2} count:{3} sample:{4}"
                            //    , i, samp, sample_data[samp]
                            //    , voice.count, voice.sample);
                            //}
                        }

                        remaining -= samples;
					}
                }
            }

			//memcpy(outputs[1], outputs[0], samples * sizeof(*outputs[0]));
			for (i = 0; i < samples; i++)
			{
				outputs[1][i] = outputs[0][i];
            }

        }
Esempio n. 2
0
        public static int okim6295_status_r()
        {
            int i, result;

            result = 0xf0;
            Sound.okistream.stream_update();
            for (i = 0; i < 4; i++)
            {
                ADPCMVoice voice = OKI.voice[i];
                if (voice.playing)
                {
                    result |= 1 << i;
                }
            }
            return(result);
        }
Esempio n. 3
0
		private void generate_adpcm(okim6295_state chip, ADPCMVoice voice, short[] buffer, int samples)
		{
			int ptrBuffer = 0;

			/* if this voice is active */
			if (voice.playing != 0)
			{
				//System.Console.Write("base_offset[{0:X}] sample[{1:X}] count[{2:X}]\n", voice.base_offset, voice.sample, voice.count);
				int iBase = (int)voice.base_offset;
				int sample = (int)voice.sample;
				int count = (int)voice.count;

				/* loop while we still have samples to generate */
				while (samples != 0)
				{
					/* compute the new amplitude and update the current step */
					//int nibble = memory_raw_read_byte(chip->device->space(), base + sample / 2) >> (((sample & 1) << 2) ^ 4);
					//System.Console.Write("nibblecal1[{0:d}]2[{1:d}]\n", iBase + sample / 2, (((sample & 1) << 2) ^ 4));
					byte nibble = (byte)(memory_raw_read_byte(chip, iBase + sample / 2) >> (((sample & 1) << 2) ^ 4));
					//System.Console.Write( "nibble[{0:X}]\n", nibble);

					/* output to the buffer, scaling by the volume */
					/* signal in range -2048..2047, volume in range 2..32 => signal * volume / 2 in range -32768..32767 */
					buffer[ptrBuffer++] = (short)(clock_adpcm(voice.adpcm, nibble) * voice.volume / 2);
					//System.Console.Write("*buffer[{0}]\n", buffer[ptrBuffer-1]);
					samples--;

					/* next! */
					if (++sample >= count)
					{
						voice.playing = 0;
						break;
					}
				}

				/* update the parameters */
				voice.sample = (uint)sample;
			}

			/* fill the rest with silence */
			while (samples-- != 0)
			{
				buffer[ptrBuffer++] = 0;
			}
		}
Esempio n. 4
0
		/**********************************************************************************************

			 okim6295_status_r -- read the status port of an OKIM6295-compatible chip

		***********************************************************************************************/

		//READ8_DEVICE_HANDLER( okim6295_r )
		private byte okim6295_r(byte ChipID, int offset)
		{
			//okim6295_state *info = get_safe_token(device);
			okim6295_state info = OKIM6295Data[ChipID];
			int i, result;

			result = 0xf0;  /* naname expects bits 4-7 to be 1 */

			/* set the bit to 1 if something is playing on a given channel */
			//stream_update(info->stream);
			for (i = 0; i < okim6295_state.OKIM6295_VOICES; i++)
			{
				ADPCMVoice voice = info.voice[i];

				/* set the bit if it's playing */
				if (voice.playing != 0)
					result |= 1 << i;
			}

			return (byte)result;
		}
Esempio n. 5
0
		/**********************************************************************************************

			 okim6295_data_w -- write to the data port of an OKIM6295-compatible chip

		***********************************************************************************************/

		//WRITE8_DEVICE_HANDLER( okim6295_w )
		private void okim6295_write_command(okim6295_state info, byte data,okim6295Info Info)
		{
			//okim6295_state *info = get_safe_token(device);

			/* if a command is pending, process the second half */
			if (info.command != -1)
			{
				int temp = data >> 4, i, start, stop;
				int iBase;

				/* the manual explicitly says that it's not possible to start multiple voices at the same time */
//				if (temp != 0 && temp != 1 && temp != 2 && temp != 4 && temp != 8)
//					System.Console.Write("OKI6295 start %x contact MAMEDEV\n", temp);

				/* update the stream */
				//stream_update(info->stream);

				/* determine which voice(s) (voice is set by a 1 bit in the upper 4 bits of the second byte) */
				for (i = 0; i < okim6295_state.OKIM6295_VOICES; i++, temp >>= 1)
				{
					if ((temp & 1) != 0)
					{
						ADPCMVoice voice = info.voice[i];

						/* determine the start/stop positions */
						iBase = info.command * 8;

						//start  = memory_raw_read_byte(device->space(), base + 0) << 16;
						start = memory_raw_read_byte(info, iBase + 0) << 16;
						start |= memory_raw_read_byte(info, iBase + 1) << 8;
						start |= memory_raw_read_byte(info, iBase + 2) << 0;
						start &= 0x3ffff;
						Info.chInfo[i].stAdr = start;

						stop = memory_raw_read_byte(info, iBase + 3) << 16;
						stop |= memory_raw_read_byte(info, iBase + 4) << 8;
						stop |= memory_raw_read_byte(info, iBase + 5) << 0;
						stop &= 0x3ffff;
						Info.chInfo[i].edAdr = stop;

						/* set up the voice to play this sample */
						if (start < stop)
						{
							if (voice.playing == 0) /* fixes Got-cha and Steel Force */
							{
								voice.playing = 1;
								voice.base_offset = (uint)start;
								voice.sample = 0;
								voice.count = (uint)(2 * (stop - start + 1));

								/* also reset the ADPCM parameters */
								reset_adpcm(voice.adpcm);
								voice.volume = (uint)volume_table[data & 0x0f];
								Info.keyon[i] = true;
							}
							else
							{
								//logerror("OKIM6295:'%s' requested to play sample %02x on non-stopped voice\n",device->tag(),info->command);
								// just displays warnings when seeking
								//logerror("OKIM6295: Voice %u requested to play sample %02x on non-stopped voice\n",i,info->command);
							}
						}
						/* invalid samples go here */
						else
						{
							//logerror("OKIM6295:'%s' requested to play invalid sample %02x\n",device->tag(),info->command);
							//System.Console.Write("OKIM6295: Voice {0}  requested to play invalid sample {1:X2} StartAddr {2:X} StopAdr {3:X} \n", i, info.command, start, stop);
							voice.playing = 0;
						}
					}
				}

				/* reset the command */
				info.command = -1;
			}

			/* if this is the start of a command, remember the sample number for next time */
			else if ((data & 0x80) != 0)
			{
				info.command = data & 0x7f;
			}

			/* otherwise, see if this is a silence command */
			else
			{
				int temp = data >> 3, i;

				/* update the stream, then turn it off */
				//stream_update(info->stream);

				/* determine which voice(s) (voice is set by a 1 bit in bits 3-6 of the command */
				for (i = 0; i < okim6295_state.OKIM6295_VOICES; i++, temp >>= 1)
				{
					if ((temp & 1) != 0)
					{
						ADPCMVoice voice = info.voice[i];

						voice.playing = 0;
					}
				}
			}
		}
Esempio n. 6
0
 public ADPCM()
 {
     this.sound_num = Mame.SOUND_ADPCM;
     this.name = "ADPCM";
     for (int i = 0; i < Mame.MAX_ADPCM; i++) adpcm[i] = new ADPCMVoice();
 }
Esempio n. 7
0
        static void generate_adpcm(ADPCMVoice voice, _ShortPtr buffer, int samples)
        {
            /* if this voice is active */
            if (voice.playing != 0)
            {
                _BytePtr _base = voice._base;
                int sample = (int)voice.sample;
                int signal = (int)voice.signal;
                int count = (int)voice.count;
                int step = (int)voice.step;
                int val;

                /* loop while we still have samples to generate */
                while (samples != 0)
                {
                    /* compute the new amplitude and update the current step */
                    val = _base[sample / 2] >> (((sample & 1) << 2) ^ 4);
                    signal += diff_lookup[step * 16 + (val & 15)];

                    /* clamp to the maximum */
                    if (signal > 2047)
                        signal = 2047;
                    else if (signal < -2048)
                        signal = -2048;

                    /* adjust the step size and clamp */
                    step += index_shift[val & 7];
                    if (step > 48)
                        step = 48;
                    else if (step < 0)
                        step = 0;

                    /* output to the buffer, scaling by the volume */
                    buffer.write16(0, (ushort)(signal * voice.volume / 16));
                    buffer.offset += 2;
                    samples--;

                    /* next! */
                    if (++sample > count)
                    {
                        voice.playing = 0;
                        break;
                    }
                }

                /* update the parameters */
                voice.sample = (uint)sample;
                voice.signal = (uint)signal;
                voice.step = (uint)step;
            }

            /* fill the rest with silence */
            while (samples-- != 0)
            {
                buffer.write16(0, 0);
                buffer.offset += 2;
            }
        }