Pergunta

I am currently trying to learn how to use Alsa to play back an audio file. I seem to have it most of the way, the file loads and plays, but I have to decrease the frequency by half to get it to play correctly. Why is this and how can I fix it?

Here is the Vala code I am currently using:

using Alsa;
using Gee;
using OGG;


namespace SoundTest
{
    public class Sound : Object
    {
        private PcmDevice sound_device;
        private char[] sound_data;

        private uint8[] alsa_data;
        private long bit_rate;

        public class Sound()
        {
        }

        ~Sound()
        {
            sound_device.drain();
            sound_device.close();
        }

        public void init()
        {
            read_sound_file();
            setup_sound_player();
        }

        public void play_sound_file()
        {
            sound_device.writei(alsa_data, sound_device.bytes_to_frames(alsa_data.length));
        }

        private uint8[] convert_data(char[] buffer)
        {
            uint8[] conversion;

            // Just need to convert to an array of uint8s.
            conversion = new uint8[buffer.length];
            for (int i = 0; i < buffer.length; i++)
            {
                conversion[i] = (uint8)buffer[i];
            }

            return conversion;
        }

        private void setup_sound_player()
        {
            // Open the sound device.
            if (PcmDevice.open(out sound_device, "default", PcmStream.PLAYBACK, 0) != 0)
            {
                critical("Unable to open a sound device\n");
                return;
            }

            // Set the parameters to use for playback.
            if (sound_device.set_params(PcmFormat.S16_LE, PcmAccess.RW_INTERLEAVED, 2, (int)bit_rate/2, 1, 500000) != 0)
            {
                critical("Could not set params properly\n");
                return;
            }

            // Prepare the device for playback.
            if (sound_device.prepare() != 0)
            {
                critical("Could not prepare the device\n");
                return;
            }
        }

        private void read_sound_file()
        {
            char[] buffer;
            int stream;
            long bytesRead;
            string filename;
            File inputFile;
            Info? soundInfo = null;
            Vorbis soundFile;
            ArrayList<char> data;

            filename = "./Median_test.ogg";

            // Make sure the file exists.
            inputFile = File.new_for_path(filename);
            if (inputFile.query_exists())
            {
                // Set the file to be read.
                message("Reading file: %s\n", filename);
                soundFile = Vorbis(filename);

                // Get the information about the sound file.
                soundInfo = soundFile.get_info(-1);

                if (soundInfo != null)
                {
                    stdout.printf("Version: %d\nChannels: %d\nRate: %ld\nBitrate: %ld, %ld, %ld\n\n",
                                  soundInfo.version, soundInfo.channels,
                                  soundInfo.rate, soundInfo.bitrate_lower,
                                  soundInfo.bitrate_nominal, soundInfo.bitrate_upper);

                    // Store the bitrate information of the sound file.
                    bit_rate = soundInfo.rate;
                }

                // Read the data from the file. Here I read a small array worth of
                // data and then store it in an array list. I then need to turn
                // that array list into a single array. I wish there was a function
                // to do it from the list, but I'll just loop.
                buffer = new char[4096];
                stream = 0;
                data = new ArrayList<char>();
                bytesRead = soundFile.read(buffer, 0, 2, 1, ref stream);
                while (bytesRead > 0)
                {
                    for (int i = 0; i < bytesRead; i++)
                    {
                        data.add(buffer[i]);
                    }

                    bytesRead = soundFile.read(buffer, 0, 2, 1, ref stream);
                }
                stdout.printf("Bytes read: %ld\n", bytesRead);

                sound_data = new char[data.size];
                for (int i = 0; i < data.size; i++)
                {
                    sound_data[i] = data[i];
                }

                // Now convert the vorbis data into the type of data alsa needs.
                alsa_data = convert_data(sound_data);
            }
            else
            {
                critical("No such file:\n\t%s\n\n", filename);
            }
        }

        public static int main(string[] args)
        {
            Sound test;

            stdout.printf("Starting Sound Test\n");

            test = new Sound();
            test.init();
            test.play_sound_file();

            stdout.printf("Done\n");


            return 0;
        }
    }
}

Thank you for any help you can give.

Foi útil?

Solução

You are configuring the sound device for two channels, but that file actually has only one.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top