Модераторы: Partizan, gambit

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Разбиение звукового файла на несколько частей 
V
    Опции темы
agealex
Дата 2.6.2009, 10:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 207
Регистрация: 2.9.2007

Репутация: нет
Всего: нет



Проект на С# 3.5 на мобильной платформе.

Есть:
1. файл со звуком. в котором содержатся все звуки проекта 
2. Файл с разбиением в байтах - с какого байта начинается какой участок звука

Нужно:
Проигрывать звук с определенного байта до определенного байта.
Как это сделать? smile 
PM MAIL   Вверх
agealex
Дата 3.6.2009, 02:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 207
Регистрация: 2.9.2007

Репутация: нет
Всего: нет



Пробывал различные варианты но при всех, если использовать SoundPlayer вылетает ошибка при вызове Play();:dash1 
вот один из вариантов: 
Код

               FileStream fs = File.Open("@\\rus.wav", FileMode.Open);
               byte[] soundData = new Byte[fs.Length];
               int count = fs.Read(soundData, 0, (int)fs.Length);   
               Stream fs2 = new MemoryStream();
               fs2.Write(soundData, 0, soundData.Length);
               fs2.Position = 0;
               System.Media.SoundPlayer player2 = new System.Media.SoundPlayer(fs2);
               SoundPlayer player = new SoundPlayer(fs);
               player.Load();
               player.Play(); // ругается всегда в этом месте , к сожалению еще не успел узнать на что ругается требует "NETCFv35.Messages.EN.wm.cab", еще не установил


В общем проблема в том что он не может проиграть имеющийся буфер прочитанный из wav файла, буду рад любым вариантам
PM MAIL   Вверх
Экскалупатор
Дата 3.6.2009, 07:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

Репутация: 11
Всего: 24



using (FileStream fs = new FileStream(@"C:\WINDOWS\Media\tada.wav", FileMode.Open))
            {
                byte[] b = new byte[fs.Length];
                fs.Read(b, 0, 30000);
                MemoryStream ms = new MemoryStream(b);
                System.Media.SoundPlayer sound = new System.Media.SoundPlayer(ms);
                sound.Play();
            }
PM MAIL ICQ   Вверх
Экскалупатор
Дата 3.6.2009, 09:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

Репутация: 11
Всего: 24



хотя это немного не то, при попытке изменить начало позиции для чтения выдает ошибку: The wave header is corrupt. почему не знаю. может кто нить знает? тоже интересует этот вопрос...
PM MAIL ICQ   Вверх
Partizan
Дата 3.6.2009, 11:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Let's do some .NET
****


Профиль
Группа: Модератор
Сообщений: 2828
Регистрация: 19.12.2005
Где: Санкт-Петербург

Репутация: 18
Всего: 67



Экскалупатор, потому что в начале wav- файла должен быть соответствующий формату заголовок...


--------------------
СУВ,
       Partizan.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Экскалупатор
Дата 3.6.2009, 11:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

Репутация: 11
Всего: 24



Partizan, это я уже понял.
вопрос как все таки сделать что бы можно было проигрывать из любого места. перезаписывать файл? это не выход... нужно наверное как то извлечь заголовок и запихать его в свой поток, но как?
PM MAIL ICQ   Вверх
agealex
Дата 3.6.2009, 11:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 207
Регистрация: 2.9.2007

Репутация: нет
Всего: нет



Да собственно оказалось просто - считываешь заголовок из файла, затем и пишешь его в нужный тебе буфер, затем дозаписываешь при надобности в него нужные тебе данные и меняешь поле отвечающее за размер файла.
PM MAIL   Вверх
agealex
Дата 3.6.2009, 12:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 207
Регистрация: 2.9.2007

Репутация: нет
Всего: нет



а как сделать плавный переход от одного буфера к другому что бы непрерывно играл? Если я использую 2 буфера?
PM MAIL   Вверх
Экскалупатор
Дата 3.6.2009, 12:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

Репутация: 11
Всего: 24



agealex, можно посмотреть что получилось(выложите код, плиз)?

 smile 
PM MAIL ICQ   Вверх
agealex
Дата 3.6.2009, 16:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 207
Регистрация: 2.9.2007

Репутация: нет
Всего: нет



Там считываешь с начала массива  40 байт - это твой заголовок (весь заголовок занимает 44 байта учти при поправке на считывание,последние  4 байта длинна тела) - сохраняешь его в массив, затем при считывание буффера с нужного места дописываешь к заголовку сначала 4 байта длины будующего тела, а уж потом и само тело - и проигрываешь его, код вечером выложу.

Это сообщение отредактировал(а) agealex - 3.6.2009, 16:38
PM MAIL   Вверх
agealex
Дата 4.6.2009, 00:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 207
Регистрация: 2.9.2007

Репутация: нет
Всего: нет



В коде это выглядит вот так тут кусок класса аудио, осталось разобраться только с последывательным пройгрышем массивов, да всю эту штуку надо запускать либо в потоке либо самое простое  - в таймере

Если где предожите оптимизировать милости прошу


Код

 class Audio
    {
        #region declaretion

        private const byte WavHeaderSize = 40; //Размер заголовка Wav файла без размера тела (4 байта еще)
        private const byte WavHeaderBodyLenghSize = 4;// Размер тела WAV файла

        private const String WavFileName = "\\rus.wav"; // Название фалйла и путь к нему

        private byte CurrentBuffId = 1;
        public byte[] SoundBuffFirst;
        public byte[] SoundBuffSecond;

        public int BuffSize = 60000; //размер буфера
        public SoundPlayer Player;

        private FileStream FileStreamWav;
        private Stream SoundStream;

        #endregion

        public Audio()
        {
            //Буфера wav фала
            SoundBuffFirst = new byte[BuffSize]; 
            SoundBuffSecond = new byte[BuffSize];

            FileStreamWav = File.Open(WavFileName, FileMode.Open);
            FileStreamWav.Read(SoundBuffFirst, 0, WavHeaderSize + 4);
            FileStreamWav.Read(SoundBuffSecond, 0, WavHeaderSize);
            
            SoundStream = new MemoryStream();
            Player = new SoundPlayer();
          
        }

        //Воспроизводит WAV файлы
        public void PlaySound(int StartPosition, int StopPosition)
        {
            int PlayingSoundSize = 0; // Размер тела wav файла
            byte[] DataLenArray;
            if ((StopPosition - StartPosition) <= (BuffSize - WavHeaderSize - WavHeaderBodyLenghSize))
            {
                PlayingSoundSize = StopPosition - StartPosition;

                DataLenArray = BitConverter.GetBytes(PlayingSoundSize);
                DataLenArray.CopyTo(SoundBuffFirst, WavHeaderSize);
                DataLenArray = BitConverter.GetBytes(PlayingSoundSize + WavHeaderSize - WavHeaderBodyLenghSize);
                DataLenArray.CopyTo(SoundBuffFirst, WavHeaderBodyLenghSize);
               
                FileStreamWav.Position = StartPosition;
                FileStreamWav.Read(SoundBuffFirst, WavHeaderSize + WavHeaderBodyLenghSize, PlayingSoundSize);
                SoundStream.Write(SoundBuffFirst, 0, PlayingSoundSize + WavHeaderSize + WavHeaderBodyLenghSize);
                SoundStream.Position = 0;
                
                Player.Stream = SoundStream;
                Player.Stream.Position = 0;
                Player.Load();
                Player.Play();
            }


там оказалось 2 места  в которых длина хранится вот кстати структура кому интересно заголовка wav  файла (он на С++ - ну какой нашел просто так глянуть)
Код

struct head_data
 {
  public:
  char s1[4];             // 'RIFF' - сигнатура - 4 байта
  long len1;              // длина всего оставшегося  - long - 4 байта             -- вот его нужно менять
  char s2[8];             // 'WAVEfmt '  - сигнатура - 8 байт
  long d_size;            // размер блока данных заголовка - обычно 16 - long - 4 байта

  short int format;       // формат данных  - short int - 2 байта
  // 1-PCM, 2-ADPCM, ... , 85-MPEG Layer-3, ... sorry, it's all that i know :-(
  short int channels;     // число каналов (моно-1/стерео-2) - short int - 2 байта
  long discret;           // частота дискретизации - long - 4 байта
  long stream;            // поток, байт/сек, = (частота дискр * алигмент) - long - 4 байта
  short int bl_align;     // алигмент, (байт за 1 отсчет = channels*bit/8) - short int - 2 байта
  short int bitrate;      // число бит при оцифровке (8/16) - short int - 2 байта

  char s3[4];             // 'data' - сигнатура - 4 байта
  long len2;              // длина следующих после этого чистых wave-данных - long - 4 байта        -- и его тоже 
  //Summary 44 байта
 };


Это сообщение отредактировал(а) agealex - 4.6.2009, 01:18
PM MAIL   Вверх
Экскалупатор
Дата 4.6.2009, 11:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

Репутация: 11
Всего: 24



agealex, спасибо, интересная инфа, но по сути это почти перезапись файла, т.е. мы вырезаем то что нам надо и пере собираем все в новом потоке, но мне кажется должен быть способ попроще, ведь по сути поток байтов из файла не меняется, просто нужно его запускать из разных мест...
PM MAIL ICQ   Вверх
agealex
Дата 4.6.2009, 18:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 207
Регистрация: 2.9.2007

Репутация: нет
Всего: нет



Ну в принцепи можно попробывать, закачать один раз буфер целиком в SoundPlayer.Stream и меняя его позицию запускать в разных частях , и соответственно останавливать по достижению определеннойй позиции, так скорее даже будет быстрее, так как одни из существенных недостатков данного кода к сожалению выяснилось, что является временная задержка порядка  1 - 4х секунд . сегодня попробую потом выложу если получится удачнее.
PM MAIL   Вверх
agealex
Дата 4.6.2009, 20:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 207
Регистрация: 2.9.2007

Репутация: нет
Всего: нет



Вот конечная версия, более упрощенная чем преведущие, вроде все лишнее из нее убрал, и исчезли проблемы с ожиданием запуска, размерами буфера и необходимость в пинпонге буферами. Если еще больше можно упростить не стесняйтесь пишите.
Код

using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Media;
using System.IO;
namespace Audio
{
    class Audio
    {
        #region declaretion

        private const byte WavHeaderSize = 40; //Размер заголовка Wav файла без размера тела (4 байта еще)
        private const byte WavHeaderBodyLenghSize = 4;// Размер тела WAV файла

        private const String WavFileName = "\\rus.wav"; // Название фалйла и путь к нему

        
        public byte[] SoundBuffHeader;
        private byte[] SoundBuffMain;


        public SoundPlayer Player;
        private FileStream FileStreamWav;

        #endregion

        public Audio()
        {
            //Буфера wav фала
            SoundBuffHeader = new byte[WavHeaderSize + WavHeaderBodyLenghSize]; 
            FileStreamWav = File.Open(WavFileName, FileMode.Open);
            SoundBuffMain = new byte[FileStreamWav.Length - WavHeaderSize - WavHeaderBodyLenghSize];
            
            #region BufferRead
            // Считывание всех буфферов
            FileStreamWav.Position = 0;
            FileStreamWav.Read(SoundBuffHeader, 0, WavHeaderSize); // Заголовок кроме последней длины
            FileStreamWav.Position = WavHeaderSize + WavHeaderBodyLenghSize;
            FileStreamWav.Read(SoundBuffMain,0,SoundBuffMain.Length); // Весь файл кроме заголовка

            #endregion
            
            SoundStream = new MemoryStream();
            Player = new SoundPlayer();
            Player.Stream = new MemoryStream();
        }
        
        //Воспроизводит WAV файлы
        public void PlaySound(int StartPosition, int StopPosition)
        {
            int PlayingSoundSize = 0; // Размер тела wav файла
            byte[] DataLenArray;
            if ((StopPosition - StartPosition) <= (BuffSize - WavHeaderSize - WavHeaderBodyLenghSize))
            {
                PlayingSoundSize = StopPosition - StartPosition;
                // Запись в заголовок информации о размере тела файла
                DataLenArray = BitConverter.GetBytes(PlayingSoundSize);
                DataLenArray.CopyTo(SoundBuffHeader, WavHeaderSize);
                DataLenArray = BitConverter.GetBytes(PlayingSoundSize + WavHeaderSize - WavHeaderBodyLenghSize);
                DataLenArray.CopyTo(SoundBuffHeader, WavHeaderBodyLenghSize);
                //Запись заголовка в проигрываемый файл
                Player.Stream.Write(SoundBuffHeader, 0, SoundBuffHeader.Length);
                // Запись самого тела
                Player.Stream.Write(SoundBuffMain, StartPosition, PlayingSoundSize + WavHeaderSize + WavHeaderBodyLenghSize);

                Player.Stream.Position = 0;
                Player.Load();
                Player.Play();
            }
           
        }
    }
    
    
}



Это сообщение отредактировал(а) agealex - 4.6.2009, 20:35
PM MAIL   Вверх
agealex
Дата 8.6.2009, 09:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 207
Регистрация: 2.9.2007

Репутация: нет
Всего: нет



К сожалению при испытаниях выявилась странная закономерность - в независимости от места начала проигрыша , при повторном запуске воспроизводится начинало с начала.

Вот окончательная доработанная и протестированная версия:

Отличия - весь звуковой файл не записывается целиком в буфер а берутся толь ко нужные куски, как ни странно это исправило проблему неправильного места старта звукового файла, избавило от проблем с работой с большими звуковыми файлами(нехватка памяти)

Да и тут еще появился программный регулятор громкости - для комплекта smile
Код

using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Media;
using System.IO;
using System.Runtime.InteropServices;

namespace ShowDialog
{
    class Audio
    {
        #region SoundMixer
        [DllImport("coredll.dll", SetLastError = true)]
        protected static extern int waveOutSetVolume(IntPtr device, uint volume);
        //values for 'volume' are between value between 0 (off) and 65536 (max)
        //if there is only one audio device, you can set 'device' to null (or IntPtr.Zero)
        public enum Volumes : int
        {

            OFF = 0,
            LOW = 858993459,
            NORMAL = 1717986918,
            MEDIUM = -1717986919,
            HIGH = -858993460,
            VERY_HIGH = -1

        }

        [DllImport("coredll.dll", SetLastError = true)]

        internal static extern int waveOutSetVolume(IntPtr device, int volume);

        [DllImport("coredll.dll", SetLastError = true)]

        internal static extern int waveOutGetVolume(IntPtr device, ref int volume);
        public void VolumeLevelUP()
        {
            int v = (int)0;
            int Value = 0;
            waveOutGetVolume(IntPtr.Zero, ref v);
            switch (v)
            {
                case (int)Volumes.OFF:
                    Value = (int)Volumes.LOW;
                    break;
                case (int)Volumes.LOW:
                    Value = (int)Volumes.NORMAL;
                    break;
                case (int)Volumes.NORMAL:
                    Value = (int)Volumes.MEDIUM;
                    break;
                case (int)Volumes.MEDIUM:
                    Value = (int)Volumes.HIGH;
                    break;
                case (int)Volumes.HIGH:
                    Value = (int)Volumes.VERY_HIGH;
                    break;
                case (int)Volumes.VERY_HIGH:
                    Value = (int)Volumes.OFF;
                    break;
                default: Value = (int)Volumes.VERY_HIGH;
                    break;
            }
            waveOutSetVolume(IntPtr.Zero, Value);
        }
        public void VolumeLevelDown()
        {
            int v = (int)0;
            int Value = 0;
            waveOutGetVolume(IntPtr.Zero, ref v);
            switch (v)
            {
                case (int)Volumes.OFF:
                    Value = (int)Volumes.VERY_HIGH;
                    break;
                case (int)Volumes.LOW:
                    Value = (int)Volumes.OFF;
                    break;
                case (int)Volumes.NORMAL:
                    Value = (int)Volumes.LOW;
                    break;
                case (int)Volumes.MEDIUM:
                    Value = (int)Volumes.NORMAL;
                    break;
                case (int)Volumes.HIGH:
                    Value = (int)Volumes.MEDIUM;
                    break;
                case (int)Volumes.VERY_HIGH:
                    Value = (int)Volumes.HIGH;
                    break;
                default: Value = (int)Volumes.OFF;
                    break;
            }
            waveOutSetVolume(IntPtr.Zero, Value);
        }
        
        #endregion


        #region declaretion

        private const byte WavHeaderSize = 40; //Размер заголовка Wav файла без размера тела (4 байта еще)
        private const byte WavHeaderBodyLenghSize = 4;// Размер тела WAV файла

        private const String WavFileName = "\\rus.wav"; // Название фалйла и путь к нему

        public byte[] SoundBuffHeader;
        private byte[] SoundBuffMain;

        public int BuffSize = 600000; //размер буфера
        public SoundPlayer Player;

        private FileStream FileStreamWav;
        private Stream SoundStream;

        #endregion

        public Audio()
        {
            //Буфера wav фала
            SoundBuffHeader = new byte[WavHeaderSize + WavHeaderBodyLenghSize];
            FileStreamWav = File.Open(WavFileName, FileMode.Open);
            SoundBuffMain = new byte[FileStreamWav.Length - WavHeaderSize - WavHeaderBodyLenghSize];

            #region BufferRead
            // Считывание заголовка
            FileStreamWav.Position = 0;
            FileStreamWav.Read(SoundBuffHeader, 0, WavHeaderSize); // Заголовок кроме последней длины
         

            #endregion

            SoundStream = new MemoryStream();
            Player = new SoundPlayer();
            Player.Stream = new MemoryStream();
        }

        //Воспроизводит WAV файлы
        public void PlaySound(int StartPosition, int StopPosition)
        {
            Player = new SoundPlayer();
            Player.Stream = new MemoryStream();
            int PlayingSoundSize = 0; // Размер тела wav файла
            byte[] DataLenArray;
           
            PlayingSoundSize = StopPosition - StartPosition;
            // Запись в заголовок информации о размере тела файла
            DataLenArray = BitConverter.GetBytes(PlayingSoundSize);
            DataLenArray.CopyTo(SoundBuffHeader, WavHeaderSize);
            DataLenArray = BitConverter.GetBytes(PlayingSoundSize + WavHeaderSize - WavHeaderBodyLenghSize);
            DataLenArray.CopyTo(SoundBuffHeader, WavHeaderBodyLenghSize);
            
            //Запись заголовка в проигрываемый файл
            Player.Stream.Position = 0;
            Player.Stream.Write(SoundBuffHeader, 0, SoundBuffHeader.Length);
            // Запись самого тела
            
            byte[] test = new byte[PlayingSoundSize];

            FileStreamWav.Position = StartPosition;
            FileStreamWav.Read(test, 0, PlayingSoundSize); // Весь файл кроме заголовка

            Player.Stream.Write(test, 0, test.Length);

            Player.Stream.Position = 0;
            
            Player.Load();
            Player.Play();
           

        }
        //Остановка плеера
        public void StopPlaying()
        {
            Player.Stop();
        }
    }
}



Это сообщение отредактировал(а) agealex - 8.6.2009, 09:43
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.1767 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.