示例#1
0
        /// <summary>
        ///     Set output sound format
        /// </summary>
        /// <param name="ay">pointer to ayemu_t structure</param>
        /// <param name="freq">sound freq (44100 for example)</param>
        /// <param name="chans">number of channels (1-mono, 2-stereo)</param>
        /// <param name="bits"> now supported only 16 and 8.</param>
        /// <returns>
        ///         1 on success, \b 0 if error occure
        /// </returns>
        public static int ayemu_set_sound_format(ayemu_ay_t ay, int freq, int chans, int bits)
        {
            if (!check_magic(ay))
            {
                return(0);
            }

            if (!(bits == 16 || bits == 8))
            {
                ayemu_err = "Incorrect bits value";
                return(0);
            }
            else if (!(chans == 1 || chans == 2))
            {
                ayemu_err = "Incorrect number of channels";
                return(0);
            }
            else if (freq < 50)
            {
                ayemu_err = "Incorrect output sound freq";
                return(0);
            }
            else
            {
                ay.sndfmt.freq     = freq;
                ay.sndfmt.channels = chans;
                ay.sndfmt.bpc      = bits;
            }

            ay.default_sound_format_flag = 0;
            ay.dirty = true;
            return(1);
        }
示例#2
0
 public static bool check_magic(ayemu_ay_t ay)
 {
     if (ay.magic == ayemu_ay_t.MAGIC1)
     {
         return(true);
     }
     return(false);
 }
示例#3
0
        // Set chip frequency.
        public static void ayemu_set_chip_freq(ayemu_ay_t ay, int chipfreq)
        {
            if (!check_magic(ay))
            {
                return;
            }

            ay.ChipFreq = chipfreq;
            ay.dirty    = true;
        }
示例#4
0
        public static void set_table_ym(ayemu_ay_t ay, int[] tbl)       //[32]
        {
            int n;

            for (n = 0; n < 32; n++)
            {
                ay.table[n] = tbl[n];
            }
            ay.type = ayemu_chip_t.AYEMU_YM;
        }
示例#5
0
        public static void set_table_ay(ayemu_ay_t ay, int[] tbl)       //[16]
        {
            int n;

            for (n = 0; n < 32; n++)
            {
                ay.table[n] = tbl[n / 2];
            }
            ay.type = ayemu_chip_t.AYEMU_AY;
        }
示例#6
0
        public static void prepare_generation(ayemu_ay_t ay)
        {
            int vol, max_l, max_r;

            if (!ay.dirty)
            {
                return;
            }

            if (!bEnvGenInit)
            {
                gen_env();
            }

            if ((ay.default_chip_flag) != 0)
            {
                ayemu_set_chip_type(ay, ayemu_chip_t.AYEMU_AY, null);
            }

            if ((ay.default_stereo_flag) != 0)
            {
                ayemu_set_stereo(ay, ayemu_stereo_t.AYEMU_ABC, null);
            }

            if ((ay.default_sound_format_flag) != 0)
            {
                ayemu_set_sound_format(ay, 44100, 2, 16);
            }

            ay.ChipTacts_per_outcount = ay.ChipFreq / ay.sndfmt.freq / 8;

            {  // GenVols
                int n, m;
                int vol2;
                for (n = 0; n < 32; n++)
                {
                    vol2 = ay.table[n];
                    for (m = 0; m < 6; m++)
                    {
                        ay.vols[m][n] = (int)(((double)vol2 * ay.eq[m]) / 100);
                    }
                }
            }

            /* ???????????? ????????? ??????????? ???????????? ????????
             * ???????????????, ??? ? vols [x][31] ????? ????? ??????? ?????????
             * TODO: ??????? ???????? ?? ??? ;-)
             */
            max_l         = ay.vols[0][31] + ay.vols[2][31] + ay.vols[4][31];
            max_r         = ay.vols[1][31] + ay.vols[3][31] + ay.vols[5][31];
            vol           = (max_l > max_r) ? max_l : max_r; // =157283 on all defaults
            ay.Amp_Global = ay.ChipTacts_per_outcount * vol / AYEMU_MAX_AMP;

            ay.dirty = false;
        }
示例#7
0
        /// <summary>
        ///     retval ayemu_init none.
        /// </summary>
        /// <param name="ay"></param>
        public static void ayemu_init(ayemu_ay_t ay)
        {
            ay.default_chip_flag         = 1;
            ay.ChipFreq                  = AYEMU_DEFAULT_CHIP_FREQ;
            ay.default_stereo_flag       = 1;
            ay.default_sound_format_flag = 1;
            ay.dirty = true;
            ay.magic = ayemu_ay_t.MAGIC1;

            ayemu_reset(ay);
        }
示例#8
0
        /// <summary>
        ///     Set amplitude factor for each of channels (A,B anc C, tone and noise).
        ///     Factor's value must be from (-100) to 100.
        /// </summary>
        /// <param name="ay">pointer to ayemu_t structure</param>
        /// <param name="stereo_type">type of stereo</param>
        /// <param name="custom_eq">null or array with custom table of mixer layout.</param>
        /// <returns>
        ///     1 if OK, 0 if error occures.
        /// </returns>
        public static int ayemu_set_stereo(ayemu_ay_t ay, ayemu_stereo_t stereo_type, int[] custom_eq)
        {
            int i;
            int chip;

            if (!check_magic(ay))
            {
                return(0);
            }

            if (stereo_type != ayemu_stereo_t.AYEMU_STEREO_CUSTOM && custom_eq != null)
            {
                ayemu_err = "Stereo type not custom, 'custom_eq' parametr must be NULL";
                return(0);
            }

            chip = (ay.type == ayemu_chip_t.AYEMU_AY) ? 0 : 1;

            switch (stereo_type)
            {
            case ayemu_stereo_t.AYEMU_MONO:
            case ayemu_stereo_t.AYEMU_ABC:
            case ayemu_stereo_t.AYEMU_ACB:
            case ayemu_stereo_t.AYEMU_BAC:
            case ayemu_stereo_t.AYEMU_BCA:
            case ayemu_stereo_t.AYEMU_CAB:
            case ayemu_stereo_t.AYEMU_CBA:
                for (i = 0; i < 6; i++)
                {
                    ay.eq[i] = default_layout[chip][(int)stereo_type][i];
                }
                break;

            case ayemu_stereo_t.AYEMU_STEREO_CUSTOM:
                for (i = 0; i < 6; i++)
                {
                    ay.eq[i] = custom_eq[i];
                }
                break;

            default:
                ayemu_err = "Incorrect stereo type";
                return(0);
            }

            ay.default_stereo_flag = 0;
            ay.dirty = true;
            return(1);
        }
        public void InitAY(byte[] _pAYBuffer)
        {
            ay8912.init_ay8912();

            // remember buffer
            pAYBuffer = _pAYBuffer;

            // init AY structure and reset virtual chip
            AY = new ayemu_ay_t();
            ay8912.ayemu_init(AY);
            ay8912.ayemu_reset(AY);

            // will create a 1248 buffer per frame (624 samples at 16bit)
            int ret = ay8912.ayemu_set_sound_format(AY, 312 * 2 * 50, 2, 8);
        }
示例#10
0
        /** Reset AY/YM chip.
         *
         * \arg \c ay - pointer to ayemu_ay_t structure.
         * \return none.
         */
        public static void ayemu_reset(ayemu_ay_t ay)
        {
            if (!check_magic(ay))
            {
                return;
            }

            ay.cnt_a    = ay.cnt_b = ay.cnt_c = ay.cnt_n = ay.cnt_e = 0;
            ay.bit_a    = ay.bit_b = ay.bit_c = ay.bit_n = false;
            ay.env_pos  = ay.EnvNum = 0;
            ay.Cur_Seed = 0xffff;

            ay.regs.tone_a     = ay.regs.tone_b = ay.regs.tone_c = 0;
            ay.regs.noise      = 0;
            ay.regs.R7_tone_a  = ay.regs.R7_tone_b = ay.regs.R7_tone_c = false;
            ay.regs.R7_noise_a = ay.regs.R7_noise_b = ay.regs.R7_noise_c = false;
            ay.regs.vol_a      = ay.regs.vol_b = ay.regs.vol_c = 0;
            ay.regs.env_a      = ay.regs.env_b = ay.regs.env_c = false;
            ay.regs.env_freq   = ay.regs.env_style = 0;
        }
示例#11
0
        /** Set chip type. */
        public static int ayemu_set_chip_type(ayemu_ay_t ay, ayemu_chip_t type, int[] custom_table)
        {
            if (!check_magic(ay))
            {
                return(0);
            }

            if (!(type == ayemu_chip_t.AYEMU_AY_CUSTOM || type == ayemu_chip_t.AYEMU_YM_CUSTOM) && custom_table != null)
            {
                ayemu_err = "For non-custom chip type 'custom_table' param must be NULL";
                return(0);
            }

            switch (type)
            {
            case ayemu_chip_t.AYEMU_AY:
            case ayemu_chip_t.AYEMU_AY_LION17:  set_table_ay(ay, Lion17_AY_table); break;

            case ayemu_chip_t.AYEMU_YM:
            case ayemu_chip_t.AYEMU_YM_LION17:  set_table_ym(ay, Lion17_YM_table); break;

            case ayemu_chip_t.AYEMU_AY_KAY: set_table_ay(ay, KAY_AY_table); break;

            case ayemu_chip_t.AYEMU_YM_KAY: set_table_ym(ay, KAY_YM_table); break;

            case ayemu_chip_t.AYEMU_AY_CUSTOM: set_table_ay(ay, custom_table); break;

            case ayemu_chip_t.AYEMU_YM_CUSTOM: set_table_ym(ay, custom_table); break;

            default:
                ayemu_err = "Incorrect chip type";
                return(0);
            }

            ay.default_chip_flag = 0;
            ay.dirty             = true;
            return(1);
        }
示例#12
0
 void ayemu_free(ayemu_ay_t ay)
 {
     //
     return;
 }
示例#13
0
        /// <summary>
        /// Generate sound. Fill sound buffer with current register data
        /// </summary>
        /// <param name="ay">ay chip</param>
        /// <param name="buff">8 bit buffer to fill - or null</param>
        /// <param name="buff16">16 bit buffer to fill - or null</param>
        /// <param name="frame_count">size of buffer</param>
        public static int ayemu_gen_sound(ayemu_ay_t ay, byte[] buff, UInt16[]  buff16, int frame_count, int _index)
        {
            int mix_l, mix_r;
            int tmpvol;
            int m;

            byte[]   char_buf   = buff;
            UInt16[] short_buf  = buff16;
            int      buff_index = _index;

            if (!check_magic(ay))
            {
                return(0);
            }

            prepare_generation(ay);

            while (frame_count-- > 0)
            {
                mix_l = mix_r = 0;

                for (m = 0; m < ay.ChipTacts_per_outcount; m++)
                {
                    if (++ay.cnt_a >= ay.regs.tone_a)
                    {
                        ay.cnt_a = 0;
                        ay.bit_a = !ay.bit_a;
                    }
                    if (++ay.cnt_b >= ay.regs.tone_b)
                    {
                        ay.cnt_b = 0;
                        ay.bit_b = !ay.bit_b;
                    }
                    if (++ay.cnt_c >= ay.regs.tone_c)
                    {
                        ay.cnt_c = 0;
                        ay.bit_c = !ay.bit_c;
                    }

                    /* GenNoise (c) Hacker KAY & Sergey Bulba */
                    if (++ay.cnt_n >= (ay.regs.noise * 2))
                    {
                        ay.cnt_n    = 0;
                        ay.Cur_Seed = (ay.Cur_Seed * 2 + 1) ^ (((ay.Cur_Seed >> 16) ^ (ay.Cur_Seed >> 13)) & 1);
                        ay.bit_n    = false;
                        if (((ay.Cur_Seed >> 16) & 1) != 0)
                        {
                            ay.bit_n = true;
                        }
                    }

                    if (++ay.cnt_e >= ay.regs.env_freq)
                    {
                        ay.cnt_e = 0;
                        if (++ay.env_pos > 127)
                        {
                            ay.env_pos = 64;
                        }
                    }

                    //#define ENVVOL Envelope[ay.regs.env_style][ay.env_pos]

                    if ((ay.bit_a | !ay.regs.R7_tone_a) & (ay.bit_n | !ay.regs.R7_noise_a))
                    {
                        tmpvol = (ay.regs.env_a) ? Envelope[ay.regs.env_style][ay.env_pos] : ay.regs.vol_a * 2 + 1;
                        mix_l += ay.vols[0][tmpvol];
                        mix_r += ay.vols[1][tmpvol];
                    }

                    if ((ay.bit_b | !ay.regs.R7_tone_b) & (ay.bit_n | !ay.regs.R7_noise_b))
                    {
                        tmpvol = (ay.regs.env_b) ? Envelope[ay.regs.env_style][ay.env_pos] : ay.regs.vol_b * 2 + 1;
                        mix_l += ay.vols[2][tmpvol];
                        mix_r += ay.vols[3][tmpvol];
                    }

                    if ((ay.bit_c | !ay.regs.R7_tone_c) & (ay.bit_n | !ay.regs.R7_noise_c))
                    {
                        tmpvol = (ay.regs.env_c) ? Envelope[ay.regs.env_style][ay.env_pos] : ay.regs.vol_c * 2 + 1;
                        mix_l += ay.vols[4][tmpvol];
                        mix_r += ay.vols[5][tmpvol];
                    }
                } /* end for (m=0; ...) */

                mix_l /= ay.Amp_Global;
                mix_r /= ay.Amp_Global;

                if (ay.sndfmt.bpc == 8)
                {
                    mix_l = (mix_l >> 8); // | 128; /* 8 bit sound */
                    mix_r = (mix_r >> 8); // | 128;
                    char_buf[_index++] = (byte)mix_l;
                    if (ay.sndfmt.channels != 1)
                    {
                        char_buf[_index++] = (byte)mix_r;
                    }
                }
                else
                {
                    short_buf[_index++] = (UInt16)mix_l;  /* 16 bit sound */
                    if (ay.sndfmt.channels != 1)
                    {
                        short_buf[_index++] = (UInt16)mix_r;
                    }
                }
            }
            return(buff_index);
        }
示例#14
0
/** Assign values for AY registers.
 *
 * You must pass array of char [14] to this function
 */
/*
 * void ayemu_set_regs(ayemu_ay_t ay, unsigned char* regs)
 *      {
 *          if (!check_magic(ay)) return;
 *
 *          //	WARN_IF_REGISTER_GREAT_THAN(1, 15);
 *          //	WARN_IF_REGISTER_GREAT_THAN(3, 15);
 *          //	WARN_IF_REGISTER_GREAT_THAN(5, 15);
 *          //	WARN_IF_REGISTER_GREAT_THAN(8, 31);
 *          //	WARN_IF_REGISTER_GREAT_THAN(9, 31);
 *          //	WARN_IF_REGISTER_GREAT_THAN(10, 31);
 *
 *          ay.regs.tone_a = regs[0] + ((regs[1] & 0x0f) << 8);
 *          ay.regs.tone_b = regs[2] + ((regs[3] & 0x0f) << 8);
 *          ay.regs.tone_c = regs[4] + ((regs[5] & 0x0f) << 8);
 *
 *          ay.regs.noise = regs[6] & 0x1f;
 *
 *          ay.regs.R7_tone_a = !(regs[7] & 0x01);
 *          ay.regs.R7_tone_b = !(regs[7] & 0x02);
 *          ay.regs.R7_tone_c = !(regs[7] & 0x04);
 *
 *          ay.regs.R7_noise_a = !(regs[7] & 0x08);
 *          ay.regs.R7_noise_b = !(regs[7] & 0x10);
 *          ay.regs.R7_noise_c = !(regs[7] & 0x20);
 *
 *          ay.regs.vol_a = regs[8] & 0x0f;
 *          ay.regs.vol_b = regs[9] & 0x0f;
 *          ay.regs.vol_c = regs[10] & 0x0f;
 *          ay.regs.env_a = regs[8] & 0x10;
 *          ay.regs.env_b = regs[9] & 0x10;
 *          ay.regs.env_c = regs[10] & 0x10;
 *          ay.regs.env_freq = regs[11] + (regs[12] << 8);
 *
 *          if (regs[13] != 0xff)
 *          {                   // R13 = 255 means continue curent envelop
 *              ay.regs.env_style = regs[13] & 0x0f;
 *              ay.env_pos = ay.cnt_e = 0;
 *          }
 *      }
 */
        /** Assign value for a single AY register.
         */
        public static void ayemu_set_reg(ayemu_ay_t ay, int reg, byte value)
        {
            if (!check_magic(ay))
            {
                return;
            }

            switch (reg)
            {
            case 0:
                ay.regs.tone_a = (ay.regs.tone_a & 0x0f00) | value;
                break;

            case 1:
                ay.regs.tone_a = (ay.regs.tone_a & 0x00ff) | ((value & 0x0f) << 8);
                break;

            case 2:
                ay.regs.tone_b = (ay.regs.tone_b & 0x0f00) | value;
                break;

            case 3:
                ay.regs.tone_b = (ay.regs.tone_b & 0x00ff) | ((value & 0x0f) << 8);
                break;

            case 4:
                ay.regs.tone_c = (ay.regs.tone_c & 0x0f00) | value;
                break;

            case 5:
                ay.regs.tone_c = (ay.regs.tone_c & 0x00ff) | ((value & 0x0f) << 8);
                break;

            case 6:
                ay.regs.noise = value & 0x1f;
                break;

            case 7:
                ay.regs.R7_tone_a = !((value & 0x01) != 0);
                ay.regs.R7_tone_b = !((value & 0x02) != 0);
                ay.regs.R7_tone_c = !((value & 0x04) != 0);

                ay.regs.R7_noise_a = !((value & 0x08) != 0);
                ay.regs.R7_noise_b = !((value & 0x10) != 0);
                ay.regs.R7_noise_c = !((value & 0x20) != 0);

                break;

            case 8:
                ay.regs.vol_a = value & 0x0f;
                ay.regs.env_a = false;
                if ((value & 0x10) != 0)
                {
                    ay.regs.env_a = true;
                }
                break;

            case 9:
                ay.regs.vol_b = value & 0x0f;
                ay.regs.env_b = false;
                if ((value & 0x10) != 0)
                {
                    ay.regs.env_b = true;
                }
                break;

            case 10:
                ay.regs.vol_c = value & 0x0f;
                ay.regs.env_c = false;
                if ((value & 0x10) != 0)
                {
                    ay.regs.env_c = true;
                }
                break;

            case 11:
                ay.regs.env_freq = (ay.regs.env_freq & 0xff00) | value;
                break;

            case 12:
                ay.regs.env_freq = (ay.regs.env_freq & 0x00ff) | (value << 8);
                break;

            case 13:
                ay.regs.env_style = value & 0x0f;
                ay.env_pos        = ay.cnt_e = 0;
                break;
            }
        }