Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/6: Рейтинг темы: голосов - 6, средняя оценка - 5.00
0 / 0 / 0
Регистрация: 16.12.2016
Сообщений: 93
1

Меняю значение высоких и низких звуковых частот

17.12.2016, 17:05. Просмотров 1248. Ответов 12
Метки нет (Все метки)


Здравствуйте!

Работаю над одним генератором звуковых частот, вернее над генератором шума. Нашёл отличную библиотеку NAudio.dll и работаю с ней. Подключил к проекту вот такой класс, в котором есть всё что мне нужно для генерации.

Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace WhiteNoiseGenerator
{
    class SignalGenerator : ISampleProvider
    {
 
        // Wave format
        private readonly WaveFormat waveFormat;
 
        // Random Number for the White Noise & Pink Noise Generator
        private readonly Random random = new Random();
 
        private readonly double[] pinkNoiseBuffer = new double[7];
 
        // Const Math
        private const double TwoPi = 2 * Math.PI;
 
        // Generator variable
        private int nSample;
 
        // Sweep Generator variable
        private double phi;
 
        /// <summary>
        /// Initializes a new instance for the Generator (Default :: 44.1Khz, 2 channels, Sinus, Frequency = 440, Gain = 1)
        /// </summary>
        public SignalGenerator()
            : this(44100, 2)
        {
 
        }
 
        /// <summary>
        /// Initializes a new instance for the Generator (UserDef SampleRate &amp; Channels)
        /// </summary>
        /// <param name="sampleRate">Desired sample rate</param>
        /// <param name="channel">Number of channels</param>
        public SignalGenerator(int sampleRate, int channel)
        {
            phi = 0;
            waveFormat = WaveFormat.CreateIeeeFloatWaveFormat(sampleRate, channel);
 
            // Default
            Type = SignalGeneratorType.Sin;
            Frequency = 440.0;
            Gain = 1;
            PhaseReverse = new bool[channel];
            SweepLengthSecs = 2;
        }
 
        /// <summary>
        /// The waveformat of this WaveProvider (same as the source)
        /// </summary>
        public WaveFormat WaveFormat
        {
            get { return waveFormat; }
        }
 
        /// <summary>
        /// Frequency for the Generator. (20.0 - 20000.0 Hz)
        /// Sin, Square, Triangle, SawTooth, Sweep (Start Frequency).
        /// </summary>
        public double Frequency { get; set; }
 
        /// <summary>
        /// Return Log of Frequency Start (Read only)
        /// </summary>
        public double FrequencyLog
        {
            get { return Math.Log(Frequency); }
        }
 
        /// <summary>
        /// End Frequency for the Sweep Generator. (Start Frequency in Frequency)
        /// </summary>
        public double FrequencyEnd { get; set; }
 
        /// <summary>
        /// Return Log of Frequency End (Read only)
        /// </summary>
        public double FrequencyEndLog
        {
            get { return Math.Log(FrequencyEnd); }
        }
 
        /// <summary>
        /// Gain for the Generator. (0.0 to 1.0)
        /// </summary>
        public double Gain { get; set; }
 
        /// <summary>
        /// Channel PhaseReverse
        /// </summary>
        public bool[] PhaseReverse { get; private set; }
 
        /// <summary>
        /// Type of Generator.
        /// </summary>
        public SignalGeneratorType Type { get; set; }
 
        /// <summary>
        /// Length Seconds for the Sweep Generator.
        /// </summary>
        public double SweepLengthSecs { get; set; }
 
        /// <summary>
        /// Reads from this provider.
        /// </summary>
        public int Read(float[] buffer, int offset, int count)
        {
            int outIndex = offset;
 
            // Generator current value
            double multiple;
            double sampleValue;
            double sampleSaw;
 
            // Complete Buffer
            for (int sampleCount = 0; sampleCount < count / waveFormat.Channels; sampleCount++)
            {
                switch (Type)
                {
                    case SignalGeneratorType.Sin:
 
                        // Sinus Generator
 
                        multiple = TwoPi * Frequency / waveFormat.SampleRate;
                        sampleValue = Gain * Math.Sin(nSample * multiple);
 
                        nSample++;
 
                        break;
 
 
                    case SignalGeneratorType.Square:
 
                        // Square Generator
 
                        multiple = 2 * Frequency / waveFormat.SampleRate;
                        sampleSaw = ((nSample * multiple) % 2) - 1;
                        sampleValue = sampleSaw > 0 ? Gain : -Gain;
 
                        nSample++;
                        break;
 
                    case SignalGeneratorType.Triangle:
 
                        // Triangle Generator
 
                        multiple = 2 * Frequency / waveFormat.SampleRate;
                        sampleSaw = ((nSample * multiple) % 2);
                        sampleValue = 2 * sampleSaw;
                        if (sampleValue > 1)
                            sampleValue = 2 - sampleValue;
                        if (sampleValue < -1)
                            sampleValue = -2 - sampleValue;
 
                        sampleValue *= Gain;
 
                        nSample++;
                        break;
 
                    case SignalGeneratorType.SawTooth:
 
                        // SawTooth Generator
 
                        multiple = 2 * Frequency / waveFormat.SampleRate;
                        sampleSaw = ((nSample * multiple) % 2) - 1;
                        sampleValue = Gain * sampleSaw;
 
                        nSample++;
                        break;
 
                    case SignalGeneratorType.White:
 
                        // White Noise Generator
                        sampleValue = (Gain * NextRandomTwo());
                        break;
 
                    case SignalGeneratorType.Pink:
 
                        // Pink Noise Generator
 
                        double white = NextRandomTwo();
                        pinkNoiseBuffer[0] = 0.99886 * pinkNoiseBuffer[0] + white * 0.0555179;
                        pinkNoiseBuffer[1] = 0.99332 * pinkNoiseBuffer[1] + white * 0.0750759;
                        pinkNoiseBuffer[2] = 0.96900 * pinkNoiseBuffer[2] + white * 0.1538520;
                        pinkNoiseBuffer[3] = 0.86650 * pinkNoiseBuffer[3] + white * 0.3104856;
                        pinkNoiseBuffer[4] = 0.55000 * pinkNoiseBuffer[4] + white * 0.5329522;
                        pinkNoiseBuffer[5] = -0.7616 * pinkNoiseBuffer[5] - white * 0.0168980;
                        double pink = pinkNoiseBuffer[0] + pinkNoiseBuffer[1] + pinkNoiseBuffer[2] + pinkNoiseBuffer[3] + pinkNoiseBuffer[4] + pinkNoiseBuffer[5] + pinkNoiseBuffer[6] + white * 0.5362;
                        pinkNoiseBuffer[6] = white * 0.115926;
                        sampleValue = (Gain * (pink / 5));
                        break;
 
                    case SignalGeneratorType.Sweep:
 
                        // Sweep Generator
                        double f = Math.Exp(FrequencyLog + (nSample * (FrequencyEndLog - FrequencyLog)) / (SweepLengthSecs * waveFormat.SampleRate));
 
                        multiple = TwoPi * f / waveFormat.SampleRate;
                        phi += multiple;
                        sampleValue = Gain * (Math.Sin(phi));
                        nSample++;
                        if (nSample > SweepLengthSecs * waveFormat.SampleRate)
                        {
                            nSample = 0;
                            phi = 0;
                        }
                        break;
 
                    default:
                        sampleValue = 0.0;
                        break;
                }
 
                // Phase Reverse Per Channel
                for (int i = 0; i < waveFormat.Channels; i++)
                {
                    if (PhaseReverse[i])
                        buffer[outIndex++] = (float)-sampleValue;
                    else
                        buffer[outIndex++] = (float)sampleValue;
                }
            }
            return count;
        }
 
        /// <summary>
        /// Private :: Random for WhiteNoise &amp; Pink Noise (Value form -1 to 1)
        /// </summary>
        /// <returns>Random value from -1 to +1</returns>
        private double NextRandomTwo()
        {
            return 2 * random.NextDouble() - 1;
        }
 
    }
 
    /// <summary>
    /// Signal Generator type
    /// </summary>
    public enum SignalGeneratorType
    {
        /// <summary>
        /// Pink noise
        /// </summary>
        Pink,
        /// <summary>
        /// White noise
        /// </summary>
        White,
        /// <summary>
        /// Sweep
        /// </summary>
        Sweep,
        /// <summary>
        /// Sine wave
        /// </summary>
        Sin,
        /// <summary>
        /// Square wave
        /// </summary>
        Square,
        /// <summary>
        /// Triangle Wave
        /// </summary>
        Triangle,
        /// <summary>
        /// Sawtooth wave
        /// </summary>
        SawTooth,
    }
}


В чём собственно проблема?
На клавише "Старт" у меня стоит такой код:

Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
WaveOut _waveOutGene = new WaveOut();
SignalGenerator wg = new SignalGenerator();
 
wg.Type = SignalGeneratorType.White; // тут выбираю цвет шума
 
float z1 = 20;  // это начальная частота
float z2 = 20000;  // это конечная частота
 
wg.Frequency = (float)(z1); // Тут назначаем Нижнюю частоту
wg.FrequencyEnd = (float)(z2); // Тут назначаем Верхнюю частоту
 
_waveOutGene.Init(wg);
_waveOutGene.Play(); // тут уже запуск самого генератора


После того как я с кода меняю частоту, допустим с 20-20 000 Гц до 15-15 000 разницы я не слышу! Считается что разницу в таких частотах можно услышать даже без каких-то специальных программ по диагностике звука, но хоть убей - я не слышу разницы между ними. Быть может мой код по изменению частот не верно написан?

Если кто знает - подскажите пожалуйста! Заранее большое спасибо!
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.12.2016, 17:05
Ответы с готовыми решениями:

Фильтры высоких и низких частот C#
Всем доброго дня! Мне нужно создать фильтры высоких и низких частот для просто сигнала и для...

Вывести низкие и высокие оценки , и количество низких и высоких оценок
«Задача» Ввести с клавиатуры количество ваших оценок за 1 семестр(от 7 до 10) , после этого ввести...

Почему некоторые игры тормозят на низких настройках сильнее, чем на высоких?
Почему на низких настройках некоторые игры тормозят больше чем на высоких?

Фильтр низких частот
формулой: On = On-1 + α(In – On-1), где O – выходное значение сигнала (отфильтрованное), In...

12
1401 / 1143 / 795
Регистрация: 29.02.2016
Сообщений: 3,505
17.12.2016, 17:26 2
http://stackoverflow.com/quest... in-c-sharp
http://stackoverflow.com/quest... et-library
https://www.codeproject.com/Ar... -Generator
0
0 / 0 / 0
Регистрация: 16.12.2016
Сообщений: 93
17.12.2016, 18:02  [ТС] 3
На сайте (первом) есть вот такой код:

C#
1
2
3
4
5
6
7
8
int sampleRate = 8000;
short[] buffer = new short[8000];
double amplitude = 0.25 * short.MaxValue;
double frequency = 1000;
for (int n = 0; n < buffer.Length; n++)
{
    buffer[n] = (short)(amplitude * Math.Sin((2 * Math.PI * n * frequency) / sampleRate));
}
Сразу вопрос - как мне "озвучить" это? Я ставлю его на событие кнопки - а он молчит
0
2262 / 1720 / 511
Регистрация: 02.08.2011
Сообщений: 4,912
17.12.2016, 19:04 4
Вы можете реализовать свои виды звука, реализуя и IWaveProvider или ISampleProvider, либо абстрактные классы.
Пример SineProvider.

Добавлено через 10 минут
Если непонятно, вот пример использования того же SineProvider:
// две кнопки - Start and Stop - и NumberUpDown для настройки частоты
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public partial class Form1 : Form
    {
        WaveOut _waveOut = new WaveOut();
        SineWaveProvider32 _waveProvider = new SineWaveProvider32();
 
        public Form1()
        {
            InitializeComponent();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            if (_waveOut.PlaybackState == PlaybackState.Playing)
                _waveOut.Stop();
           _waveOut.Play();
        }
 
        private void numericUpDown1_ValueChanged(object sender, EventArgs e)
        {
            _waveProvider.Frequency = (float)numericUpDown1.Value;
        }
 
        private void button2_Click(object sender, EventArgs e)
        {
           if (_waveOut.PlaybackState == PlaybackState.Playing)
                _waveOut.Stop();
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            _waveOut.Init(_waveProvider);
            _waveProvider.Amplitude = 100;
        }
    }
0
0 / 0 / 0
Регистрация: 16.12.2016
Сообщений: 93
17.12.2016, 19:54  [ТС] 5
IamRain, спасибо за то что объяснили как это делается при помощи SineProvider, буду пробовать через него делать белый шум)
0
2262 / 1720 / 511
Регистрация: 02.08.2011
Сообщений: 4,912
17.12.2016, 20:04 6
Цитата Сообщение от vafilkin Посмотреть сообщение
делать белый шум)
У вас же есть исходники. Можете под себя переделать.
0
0 / 0 / 0
Регистрация: 16.12.2016
Сообщений: 93
17.12.2016, 20:12  [ТС] 7
IamRain, вот как раз мне сейчас и нужно будет понять как их "совместить". Ведь в моих исходниках частота задавалась как wg.Frequency - это начальная частота, wg.FrequencyEnd - это её предел. А тут, если я верно понимаю, мне нужно будет вывести алгоритм генерации случайных чисел для белого шума, после чего выставлять диапазон частоты их генерации уже по вашему примеру.
Потому как на мой пример частоты почему-то не действуют
0
2262 / 1720 / 511
Регистрация: 02.08.2011
Сообщений: 4,912
17.12.2016, 20:34 8
Там кстати для белого шума нету зависимости от частоты:
C#
1
2
3
4
5
//...
case SignalGeneratorType.White:
                        // White Noise Generator
                        sampleValue = (Gain * NextRandomTwo());
                        break;
Добавлено через 3 минуты
Из вики:
In signal processing, white noise is a random signal having equal intensity at different frequencies
и вот:
In discrete time, white noise is a discrete signal whose samples are regarded as a sequence of serially uncorrelated random variables with zero mean and finite variance
Добавлено через 4 минуты
Там как раз случайное число от -1 до 1 генерируется. Т.е 0 - его среднее значение (про zero mean ).
Так что диапазон частот и не должен влиять на восприятие белого шума.
0
0 / 0 / 0
Регистрация: 16.12.2016
Сообщений: 93
17.12.2016, 20:38  [ТС] 9
IamRain, И всё же мне бы не помешала Ваша помощь. Я добавил этот класс к проекту, пытаюсь как то к своему звуку прикрепить параметры нового класса. Что не сделаю - выделяет красным.
0
2262 / 1720 / 511
Регистрация: 02.08.2011
Сообщений: 4,912
17.12.2016, 20:42 10
Просто в вашем коде поменяйте тип сигнал на любой другой, у которого есть зависимость от частоты, например SignalGeneratorType.Square. Задавая разную частоту вы на слух почувствуете разницу, правда если долго играться, то уши начнут болеть.
0
0 / 0 / 0
Регистрация: 16.12.2016
Сообщений: 93
17.12.2016, 21:38  [ТС] 11
IamRain, всё ровно не очень понял. Можно "понаочнее"?)
0
0 / 0 / 0
Регистрация: 16.12.2016
Сообщений: 93
29.01.2017, 18:21  [ТС] 12
Я меняю значение "SignalGenerator" и явно слышу разницу в частотах. Но там я задают только SimpleRate, а не Fraquency. Почему так?
0
2262 / 1720 / 511
Регистрация: 02.08.2011
Сообщений: 4,912
29.01.2017, 19:38 13
Покажите конечный код, sample rate тоже влияет на звучание, только скорее на качество, а не на восприятие частот.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
29.01.2017, 19:38

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь или здесь.

Нет регулировки высоких частот
Включил компьютер заметил что не регулируются высокие частоты,на самих драйверах регулировка...

Реализация фильтра низких частот
Добрый день! Подскажите пожалуйста, как реализовать программно ФНЧ. Из входных данных имею...

Измерение низких частот на STM32F100RB
Добрый день. Пытаюсь реализовать частотомер для двигателя ПТ с помощью функции захвата TIM3 2...

Расчет элементов фильтра высоких частот
Добрые люди подскажите пожалуйста как рассчитать элементы фильтра если нам известен только...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.