Esempio n. 1
0
        //-------------------------------------------------
        //  read_flac_sample - read a FLAC file as a sample
        //-------------------------------------------------
        static bool read_flac_sample(emu_file file, sample_t sample)
        {
            // seek back to the start of the file
            file.seek(0, SEEK_SET);

            // create the FLAC decoder and fill in the sample data
            flac_decoder decoder = new flac_decoder(file.core_file_get());

            sample.frequency = decoder.sample_rate();

            // error if more than 1 channel or not 16bpp
            if (decoder.channels() != 1)
            {
                return(false);
            }
            if (decoder.bits_per_sample() != 16)
            {
                return(false);
            }

            // resize the array and read
            sample.data.resize(decoder.total_samples());
            if (!decoder.decode_interleaved(sample.data, (uint32_t)sample.data.Count))
            {
                return(false);
            }

            // finish up and clean up
            decoder.finish();

            return(true);
        }
Esempio n. 2
0
        // dynamic control
        //void set_frequency(UINT8 channel, UINT32 frequency);
        //void set_volume(UINT8 channel, float volume);


        // helpers
        //-------------------------------------------------
        //  read_sample - read a WAV or FLAC file as a
        //  sample
        //-------------------------------------------------
        static bool read_sample(emu_file file, sample_t sample)
        {
            // read the core header and make sure it's a proper file
            MemoryU8 buf    = new MemoryU8(4, true); //uint8_t buf[4];
            uint32_t offset = file.read(new Pointer <uint8_t>(buf), 4);

            if (offset < 4)
            {
                osd_printf_warning("Unable to read {0}, 0-byte file?\n", file.filename());
                return(false);
            }

            // look for the appropriate RIFF tag
            if (buf[0] == 'R' && buf[1] == 'I' && buf[2] == 'F' && buf[3] == 'F')  // memcmp(&buf[0], "RIFF", 4) == 0)
            {
                return(read_wav_sample(file, sample));
            }
            else if (buf[0] == 'f' && buf[1] == 'L' && buf[2] == 'a' && buf[3] == 'C')  // memcmp(&buf[0], "fLaC", 4) == 0)
            {
                return(read_flac_sample(file, sample));
            }

            // if nothing appropriate, emit a warning
            osd_printf_warning("Unable to read {0}, corrupt file?\n", file.filename());

            return(false);
        }
Esempio n. 3
0
        //-------------------------------------------------
        //  device_post_load - handle updating after a
        //  restore
        //-------------------------------------------------
        protected override void device_post_load()
        {
            // loop over channels
            for (int channel = 0; channel < m_channels; channel++)
            {
                // attach any samples that were loaded and playing
                channel_t chan = m_channel[channel];
                if (chan.source_num >= 0 && chan.source_num < m_sample.Count)
                {
                    sample_t sample = m_sample[chan.source_num];
                    chan.source        = sample.data;
                    chan.source_length = sample.data.Count;
                    if (sample.data.Count == 0)
                    {
                        chan.source_num = -1;
                    }
                }

                // validate the position against the length in case the sample is smaller
                if (chan.source != null && chan.pos >= chan.source_length)
                {
                    if (chan.loop)
                    {
                        chan.pos %= (UInt32)chan.source_length;
                    }
                    else
                    {
                        chan.source     = null;
                        chan.source_num = -1;
                    }
                }
            }
        }
Esempio n. 4
0
        //-------------------------------------------------
        //  device_post_load - handle updating after a
        //  restore
        //-------------------------------------------------
        protected override void device_post_load()
        {
            // loop over channels
            for (int channel = 0; channel < m_channels; channel++)
            {
                // attach any samples that were loaded and playing
                channel_t chan = m_channel[channel];
                if (chan.source_num >= 0 && chan.source_num < m_sample.Count)
                {
                    sample_t sample = m_sample[chan.source_num];
                    chan.source     = new Pointer <int16_t>(sample.data); //chan.source = &sample.data[0];
                    chan.source_len = (u32)sample.data.size();
                    if (sample.data.Count == 0)
                    {
                        chan.source_num = -1;
                    }
                }

                // validate the position against the length in case the sample is smaller
                double endpos = chan.source_len;
                if (chan.source != null && chan.pos >= endpos)
                {
                    if (chan.loop)
                    {
                        double posfloor = std.floor(chan.pos);
                        chan.pos -= posfloor;
                        chan.pos += (double)((int32_t)posfloor % chan.source_len);
                    }
                    else
                    {
                        chan.source     = null;
                        chan.source_num = -1;
                    }
                }
            }
        }
Esempio n. 5
0
        // internal helpers

        //-------------------------------------------------
        //  read_wav_sample - read a WAV file as a sample
        //-------------------------------------------------
        static bool read_wav_sample(emu_file file, sample_t sample)
        {
            // we already read the opening 'RIFF' tag
            uint32_t offset = 4;

            // get the total size
            uint32_t filesize;

            MemoryU8 filesizeBuffer = new MemoryU8(4, true);

            offset += file.read(new Pointer <uint8_t>(filesizeBuffer), 4);
            if (offset < 8)
            {
                osd_printf_warning("Unexpected size offset {0} ({1})\n", offset, file.filename());
                return(false);
            }

            filesize = filesizeBuffer.GetUInt32();
            filesize = little_endianize_int32(filesize);

            // read the RIFF file type and make sure it's a WAVE file
            MemoryU8 buf = new MemoryU8(32, true);  //char [] buf = new char[32];

            offset += file.read(new Pointer <uint8_t>(buf), 4);
            if (offset < 12)
            {
                osd_printf_warning("Unexpected WAVE offset {0} ({1})\n", offset, file.filename());
                return(false);
            }

            if (!(buf[0] == 'W' && buf[1] == 'A' && buf[2] == 'V' && buf[3] == 'E'))  // memcmp(&buf[0], "WAVE", 4) != 0)
            {
                osd_printf_warning("Could not find WAVE header ({0})\n", file.filename());
                return(false);
            }

            // seek until we find a format tag
            uint32_t length;
            MemoryU8 lengthBuffer = new MemoryU8(4, true);

            while (true)
            {
                offset += file.read(new Pointer <uint8_t>(buf), 4);
                offset += file.read(new Pointer <uint8_t>(lengthBuffer), 4);
                length  = lengthBuffer.GetUInt32();
                length  = little_endianize_int32(length);
                if (buf[0] == 'f' && buf[1] == 'm' && buf[2] == 't' && buf[3] == ' ')  //if (memcmp(&buf[0], "fmt ", 4) == 0)
                {
                    break;
                }

                // seek to the next block
                file.seek(length, SEEK_CUR);
                offset += length;
                if (offset >= filesize)
                {
                    osd_printf_warning("Could not find fmt tag ({0})\n", file.filename());
                    return(false);
                }
            }

            // read the format -- make sure it is PCM
            uint16_t temp16;
            MemoryU8 temp16Buffer = new MemoryU8(2, true);

            offset += file.read(new Pointer <uint8_t>(temp16Buffer), 2);
            temp16  = temp16Buffer.GetUInt16();
            temp16  = little_endianize_int16(temp16);
            if (temp16 != 1)
            {
                osd_printf_warning("unsupported format {0} - only PCM is supported ({1})\n", temp16, file.filename());
                return(false);
            }

            // number of channels -- only mono is supported
            offset += file.read(new Pointer <uint8_t>(temp16Buffer), 2);
            temp16  = temp16Buffer.GetUInt16();
            temp16  = little_endianize_int16(temp16);
            if (temp16 != 1)
            {
                osd_printf_warning("unsupported number of channels {0} - only mono is supported ({1})\n", temp16, file.filename());
                return(false);
            }

            // sample rate
            uint32_t rate;
            MemoryU8 rateBuffer = new MemoryU8(4, true);

            offset += file.read(new Pointer <uint8_t>(rateBuffer), 4);
            rate    = rateBuffer.GetUInt32();
            rate    = little_endianize_int32(rate);

            // bytes/second and block alignment are ignored
            offset += file.read(new Pointer <uint8_t>(buf), 6);

            // bits/sample
            uint16_t bits;
            MemoryU8 bitsBuffer = new MemoryU8(2, true);

            offset += file.read(new Pointer <uint8_t>(bitsBuffer), 2);
            bits    = bitsBuffer.GetUInt16();
            bits    = little_endianize_int16(bits);
            if (bits != 8 && bits != 16)
            {
                osd_printf_warning("unsupported bits/sample {0} - only 8 and 16 are supported ({1})\n", bits, file.filename());
                return(false);
            }

            // seek past any extra data
            file.seek(length - 16, SEEK_CUR);
            offset += length - 16;

            // seek until we find a data tag
            while (true)
            {
                offset += file.read(new Pointer <uint8_t>(buf), 4);
                offset += file.read(new Pointer <uint8_t>(lengthBuffer), 4);
                length  = lengthBuffer.GetUInt32();
                length  = little_endianize_int32(length);
                if (buf[0] == 'd' && buf[1] == 'a' && buf[2] == 't' && buf[3] == 'a')  //if (memcmp(&buf[0], "data", 4) == 0)
                {
                    break;
                }

                // seek to the next block
                file.seek(length, SEEK_CUR);
                offset += length;
                if (offset >= filesize)
                {
                    osd_printf_warning("Could not find data tag ({0})\n", file.filename());
                    return(false);
                }
            }

            // if there was a 0 length data block, we're done
            if (length == 0)
            {
                osd_printf_warning("empty data block ({0})\n", file.filename());
                return(false);
            }

            // fill in the sample data
            sample.frequency = rate;

            // read the data in
            if (bits == 8)
            {
                sample.data.resize(length);
                MemoryU8 sample_data_8bit = new MemoryU8((int)length, true);
                file.read(new Pointer <uint8_t>(sample_data_8bit), length);

                // convert 8-bit data to signed samples
                Pointer <uint8_t> tempptr = new Pointer <uint8_t>(sample_data_8bit);  //uint8_t *tempptr = reinterpret_cast<uint8_t *>(&sample.data[0]);
                for (int sindex = (int)length - 1; sindex >= 0; sindex--)
                {
                    sample.data[sindex] = (int16_t)((uint8_t)(tempptr[sindex] ^ 0x80) * 256);
                }
            }
            else
            {
                // 16-bit data is fine as-is
                sample.data.resize(length / 2);
                MemoryU8 sample_data_8bit = new MemoryU8((int)length, true);
                file.read(new Pointer <uint8_t>(sample_data_8bit), length);

                // swap high/low on big-endian systems
                if (ENDIANNESS_NATIVE != ENDIANNESS_LITTLE)
                {
                    for (uint32_t sindex = 0; sindex < length / 2; sindex++)
                    {
                        sample.data[sindex] = (int16_t)little_endianize_int16(sample_data_8bit.GetUInt16((int)sindex));  //sample.data[sindex]);
                    }
                }
            }

            return(true);
        }