├── .gitattributes
├── .gitignore
├── Concurrence
├── Concurrence.vcxproj
├── Concurrence.vcxproj.filters
├── main.cpp
├── threadsafe_queue.cpp
└── threadsafe_queue.h
├── GifGenerator
├── DibReader.h
├── GifGenerator.vcxproj
├── GifGenerator.vcxproj.filters
├── gif.h
├── main.cpp
└── 未命名绘图.drawio.png
├── README.md
├── Sample.sln
├── SoundTouch
├── AAFilter.cpp
├── AAFilter.h
├── BPMDetect.cpp
├── BPMDetect.h
├── FIFOSampleBuffer.cpp
├── FIFOSampleBuffer.h
├── FIFOSamplePipe.h
├── FIRFilter.cpp
├── FIRFilter.h
├── InterpolateCubic.cpp
├── InterpolateCubic.h
├── InterpolateLinear.cpp
├── InterpolateLinear.h
├── InterpolateShannon.cpp
├── InterpolateShannon.h
├── PeakFinder.cpp
├── PeakFinder.h
├── RateTransposer.cpp
├── RateTransposer.h
├── STTypes.h
├── SoundTouch.cpp
├── SoundTouch.h
├── SoundTouch.vcxproj
├── SoundTouch.vcxproj.filters
├── TDStretch.cpp
├── TDStretch.h
├── cpu_detect.h
├── cpu_detect_x86.cpp
├── mmx_optimized.cpp
└── sse_optimized.cpp
└── wav_sound
├── MediaInfo.cpp
├── MediaInfo.h
├── Wav.h
├── main.cpp
├── wav_sound.vcxproj
└── wav_sound.vcxproj.filters
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | # Build results
10 | [Dd]ebug/
11 | [Dd]ebugPublic/
12 | [Rr]elease/
13 | x64/
14 | build/
15 | bld/
16 | [Bb]in/
17 | [Oo]bj/
18 |
19 | # Roslyn cache directories
20 | *.ide/
21 |
22 | # MSTest test Results
23 | [Tt]est[Rr]esult*/
24 | [Bb]uild[Ll]og.*
25 |
26 | #NUNIT
27 | *.VisualState.xml
28 | TestResult.xml
29 |
30 | # Build Results of an ATL Project
31 | [Dd]ebugPS/
32 | [Rr]eleasePS/
33 | dlldata.c
34 |
35 | *_i.c
36 | *_p.c
37 | *_i.h
38 | *.ilk
39 | *.meta
40 | *.obj
41 | *.pch
42 | *.pdb
43 | *.pgc
44 | *.pgd
45 | *.rsp
46 | *.sbr
47 | *.tlb
48 | *.tli
49 | *.tlh
50 | *.tmp
51 | *.tmp_proj
52 | *.log
53 | *.vspscc
54 | *.vssscc
55 | .builds
56 | *.pidb
57 | *.svclog
58 | *.scc
59 |
60 | # Chutzpah Test files
61 | _Chutzpah*
62 |
63 | # Visual C++ cache files
64 | ipch/
65 | *.aps
66 | *.ncb
67 | *.opensdf
68 | *.sdf
69 | *.cachefile
70 |
71 | # Visual Studio profiler
72 | *.psess
73 | *.vsp
74 | *.vspx
75 |
76 | # TFS 2012 Local Workspace
77 | $tf/
78 |
79 | # Guidance Automation Toolkit
80 | *.gpState
81 |
82 | # ReSharper is a .NET coding add-in
83 | _ReSharper*/
84 | *.[Rr]e[Ss]harper
85 | *.DotSettings.user
86 |
87 | # JustCode is a .NET coding addin-in
88 | .JustCode
89 |
90 | # TeamCity is a build add-in
91 | _TeamCity*
92 |
93 | # DotCover is a Code Coverage Tool
94 | *.dotCover
95 |
96 | # NCrunch
97 | _NCrunch_*
98 | .*crunch*.local.xml
99 |
100 | # MightyMoose
101 | *.mm.*
102 | AutoTest.Net/
103 |
104 | # Web workbench (sass)
105 | .sass-cache/
106 |
107 | # Installshield output folder
108 | [Ee]xpress/
109 |
110 | # DocProject is a documentation generator add-in
111 | DocProject/buildhelp/
112 | DocProject/Help/*.HxT
113 | DocProject/Help/*.HxC
114 | DocProject/Help/*.hhc
115 | DocProject/Help/*.hhk
116 | DocProject/Help/*.hhp
117 | DocProject/Help/Html2
118 | DocProject/Help/html
119 |
120 | # Click-Once directory
121 | publish/
122 |
123 | # Publish Web Output
124 | *.[Pp]ublish.xml
125 | *.azurePubxml
126 | ## TODO: Comment the next line if you want to checkin your
127 | ## web deploy settings but do note that will include unencrypted
128 | ## passwords
129 | #*.pubxml
130 |
131 | # NuGet Packages Directory
132 | packages/*
133 | ## TODO: If the tool you use requires repositories.config
134 | ## uncomment the next line
135 | #!packages/repositories.config
136 |
137 | # Enable "build/" folder in the NuGet Packages folder since
138 | # NuGet packages use it for MSBuild targets.
139 | # This line needs to be after the ignore of the build folder
140 | # (and the packages folder if the line above has been uncommented)
141 | !packages/build/
142 |
143 | # Windows Azure Build Output
144 | csx/
145 | *.build.csdef
146 |
147 | # Windows Store app package directory
148 | AppPackages/
149 |
150 | # Others
151 | sql/
152 | *.Cache
153 | ClientBin/
154 | [Ss]tyle[Cc]op.*
155 | ~$*
156 | *~
157 | *.dbmdl
158 | *.dbproj.schemaview
159 | *.pfx
160 | *.publishsettings
161 | node_modules/
162 |
163 | # RIA/Silverlight projects
164 | Generated_Code/
165 |
166 | # Backup & report files from converting an old project file
167 | # to a newer Visual Studio version. Backup files are not needed,
168 | # because we have git ;-)
169 | _UpgradeReport_Files/
170 | Backup*/
171 | UpgradeLog*.XML
172 | UpgradeLog*.htm
173 |
174 | # SQL Server files
175 | *.mdf
176 | *.ldf
177 |
178 | # Business Intelligence projects
179 | *.rdl.data
180 | *.bim.layout
181 | *.bim_*.settings
182 |
183 | # Microsoft Fakes
184 | FakesAssemblies/
185 |
186 | # LightSwitch generated files
187 | GeneratedArtifacts/
188 | _Pvt_Extensions/
189 | ModelManifest.xml
--------------------------------------------------------------------------------
/Concurrence/Concurrence.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 | {C00DFD7A-3897-4682-9640-8D6BF131AE35}
15 | Win32Proj
16 | Threadsafe_queue
17 | Concurrence
18 |
19 |
20 |
21 | Application
22 | true
23 | v120
24 | Unicode
25 |
26 |
27 | Application
28 | false
29 | v120
30 | true
31 | Unicode
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | true
45 |
46 |
47 | false
48 |
49 |
50 |
51 |
52 |
53 | Level3
54 | Disabled
55 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
56 |
57 |
58 | Console
59 | true
60 |
61 |
62 |
63 |
64 | Level3
65 |
66 |
67 | MaxSpeed
68 | true
69 | true
70 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
71 |
72 |
73 | Console
74 | true
75 | true
76 | true
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/Concurrence/Concurrence.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | 头文件
20 |
21 |
22 |
23 |
24 | 源文件
25 |
26 |
27 | 源文件
28 |
29 |
30 |
--------------------------------------------------------------------------------
/Concurrence/main.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "threadsafe_queue.h"
3 |
4 |
5 | int main()
6 | {
7 | return 0;
8 | }
--------------------------------------------------------------------------------
/Concurrence/threadsafe_queue.cpp:
--------------------------------------------------------------------------------
1 | #include "threadsafe_queue.h"
2 |
3 | using namespace std;
4 |
5 | template threadsafe_queue::threadsafe_queue()
6 | {}
7 |
8 | template threadsafe_queue::~threadsafe_queue()
9 | {}
10 |
11 | template threadsafe_queue::threadsafe_queue(const threadsafe_queue &other)
12 | {
13 | lock_guard lk(mut);
14 | data_queue = other.data_queue;
15 | }
16 |
17 | template void threadsafe_queue::push(T new_value)
18 | {
19 | lock_guard lk(mut);
20 | data_queue.push(new_value);
21 | data_cond.notify_one();
22 | }
23 |
24 | template void threadsafe_queue::wait_and_pop(T& value)
25 | {
26 | unique_lock lk(mut);
27 | data_cond.wait(lk, [this]{return !data_queue.empty(); });
28 | value = data_queue.front();
29 | data_queue.pop();
30 | }
31 |
32 | template shared_ptr threadsafe_queue::wait_and_pop()
33 | {
34 | unique_lock lk(mut);
35 | data_cond.wait(lk, [this]{return !data_queue.empty(); });
36 |
37 | shared_ptr res(make_shared(data_queue.front()));
38 | data_queue.pop();
39 | return res;
40 | }
41 |
42 | template bool threadsafe_queue::try_pop(T& value)
43 | {
44 | lock_guard lk(mut);
45 | if (data_queue.empty())
46 | return false;
47 |
48 | value = data_queue.front();
49 | data_queue.pop();
50 | return true;
51 | }
52 |
53 | template shared_ptr threadsafe_queue::try_pop()
54 | {
55 | lock_guard lk(mut);
56 | if (data_queue.empty())
57 | return shared_ptr();
58 |
59 | shared_ptr res(make_shared(data_queue.front()));
60 | data_queue.pop();
61 | return res;
62 | }
63 |
64 | template bool threadsafe_queue::empty() const
65 | {
66 | lock_guard lk(mut);
67 | return data_queue.empty();
68 | }
69 |
70 |
71 |
--------------------------------------------------------------------------------
/Concurrence/threadsafe_queue.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | template
9 | class threadsafe_queue
10 | {
11 |
12 | private:
13 | mutable std::mutex mut;
14 | std::queue data_queue;
15 | std::condition_variable data_cond;
16 |
17 | public:
18 | threadsafe_queue();
19 | threadsafe_queue(const threadsafe_queue &other);
20 | ~threadsafe_queue();
21 |
22 | void push(T new_value);
23 | void wait_and_pop(T& value);
24 | std::shared_ptr wait_and_pop();
25 | bool try_pop(T& value);
26 | std::shared_ptr try_pop();
27 | bool empty() const;
28 | };
29 |
30 |
--------------------------------------------------------------------------------
/GifGenerator/DibReader.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | typedef struct {
9 | uint8_t magic[2]; /* the magic number used to identify the BMP file:
10 | 0x42 0x4D (Hex code points for B and M).
11 | The following entries are possible:
12 | BM - Windows 3.1x, 95, NT, ... etc
13 | BA - OS/2 Bitmap Array
14 | CI - OS/2 Color Icon
15 | CP - OS/2 Color Pointer
16 | IC - OS/2 Icon
17 | PT - OS/2 Pointer. */
18 | uint32_t filesz; /* the size of the BMP file in bytes */
19 | uint32_t reserved; /* reserved. */
20 | uint32_t offset; /* the offset, i.e. starting address,
21 | of the byte where the bitmap data can be found. */
22 | } bmp_header_t;
23 |
24 | typedef struct {
25 | uint32_t header_sz; /* the size of this header (40 bytes) */
26 | uint32_t width; /* the bitmap width in pixels */
27 | uint32_t height; /* the bitmap height in pixels */
28 | uint16_t nplanes; /* the number of color planes being used.
29 | Must be set to 1. */
30 | uint16_t depth; /* the number of bits per pixel,
31 | which is the color depth of the image.
32 | Typical values are 1, 4, 8, 16, 24 and 32. */
33 | uint32_t compress_type; /* the compression method being used.
34 | See also bmp_compression_method_t. */
35 | uint32_t bmp_bytesz; /* the image size. This is the size of the raw bitmap
36 | data (see below), and should not be confused
37 | with the file size. */
38 | uint32_t hres; /* the horizontal resolution of the image.
39 | (pixel per meter) */
40 | uint32_t vres; /* the vertical resolution of the image.
41 | (pixel per meter) */
42 | uint32_t ncolors; /* the number of colors in the color palette,
43 | or 0 to default to 2n. */
44 | uint32_t nimpcolors; /* the number of important colors used,
45 | or 0 when every color is important;
46 | generally ignored. */
47 | } bmp_dib_header_t;
48 |
49 |
50 | bool bmp_read_header(FILE *fp, bmp_header_t *header)
51 | {
52 | assert(fp);
53 | assert(header);
54 |
55 | return fread(&(header->magic), sizeof(header->magic), 1, fp) &&
56 | fread(&(header->filesz), sizeof(uint32_t), 1, fp) &&
57 | fread(&(header->reserved), sizeof(uint32_t), 1, fp) &&
58 | fread(&(header->offset), sizeof(uint32_t), 1, fp) &&
59 | header->magic[0] == 0x42 && header->magic[1] == 0x4D;
60 | }
61 |
62 |
63 | bool bmp_read_dib_header(FILE *fp, bmp_dib_header_t *header)
64 | {
65 | assert(fp);
66 | assert(header);
67 |
68 | auto ret = fread(header, sizeof(bmp_dib_header_t), 1, fp);
69 | return ret > 0 ? true : false;
70 | /*return fread(&(header->header_sz), sizeof(uint32_t), 1, fp) &&
71 | fread(&(header->width), sizeof(uint32_t), 1, fp) &&
72 | fread(&(header->height), sizeof(uint32_t), 1, fp) &&
73 | fread(&(header->nplanes), sizeof(uint16_t), 1, fp) &&
74 | fread(&(header->depth), sizeof(uint16_t), 1, fp);*/
75 | }
76 |
77 |
78 | void *bmp_read_pixel_data(FILE *fp, uint32_t offset, const bmp_dib_header_t *header, size_t *buffer_size)
79 | {
80 | assert(fp);
81 | assert(header);
82 | assert(buffer_size);
83 |
84 | if (fseek(fp, offset, SEEK_SET))
85 | return NULL;
86 |
87 | *buffer_size = header->height * header->width * 3;
88 | void *buffer = malloc(*buffer_size);
89 | if (buffer)
90 | {
91 | if (!fread(buffer, 1, *buffer_size, fp))
92 | {
93 | free(buffer);
94 | buffer = NULL;
95 | }
96 | }
97 |
98 | return buffer;
99 | }
100 |
101 | bool save_bmp_data(const char *filename, const bmp_header_t *header, const bmp_dib_header_t *dib_header, const void *pixel_data)
102 | {
103 | FILE *out = fopen(filename, "wb");
104 | if (out)
105 | {
106 | //Write file header
107 | //fwrite(&header, 1,sizeof(header), out);
108 | fwrite(header->magic, 1, 2, out); // BM 2 Bytes
109 | fwrite(&header->filesz, 1, 4, out); // file size 4 Bytes
110 | fwrite(&header->reserved, 1, 4, out); // reserved bytes 4Bytes
111 | fwrite(&header->offset, 1, 4, out); // offset 4Bytes
112 |
113 | //Write dib header
114 | fwrite(dib_header, 1, sizeof(bmp_dib_header_t), out);
115 |
116 | //Write pixels
117 | fwrite(pixel_data, 1, dib_header->width * dib_header->height * dib_header->depth / 8, out);
118 | fclose(out);
119 |
120 | return true;
121 | }
122 | return false;
123 | }
124 |
--------------------------------------------------------------------------------
/GifGenerator/GifGenerator.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 | {0E87164D-B996-4526-A5A6-E6C9249248E4}
15 | Win32Proj
16 | GifGenerator
17 |
18 |
19 |
20 | Application
21 | true
22 | v120
23 | Unicode
24 |
25 |
26 | Application
27 | false
28 | v120
29 | true
30 | Unicode
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | true
44 |
45 |
46 | false
47 |
48 |
49 |
50 |
51 |
52 | Level3
53 | Disabled
54 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
55 |
56 |
57 | Console
58 | true
59 |
60 |
61 |
62 |
63 | Level3
64 |
65 |
66 | MaxSpeed
67 | true
68 | true
69 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
70 |
71 |
72 | Console
73 | true
74 | true
75 | true
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/GifGenerator/GifGenerator.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | 头文件
20 |
21 |
22 | 头文件
23 |
24 |
25 |
26 |
27 | 源文件
28 |
29 |
30 |
--------------------------------------------------------------------------------
/GifGenerator/main.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "gif.h"
3 | #include "DIBReader.h"
4 |
5 | #define _CRT_SECURE_NO_WARNINGS
6 |
7 | int main()
8 | {
9 | char *filename = "e:\\image\\11.bmp";
10 |
11 | FILE *stream = fopen(filename, "rb");
12 |
13 | char *gifname = "e:\\image\\12.gif";
14 |
15 | if (stream)
16 | {
17 | bmp_header_t header;
18 | bmp_dib_header_t dib_header;
19 | if (bmp_read_header(stream, &header) && bmp_read_dib_header(stream, &dib_header))
20 | {
21 | size_t buffer_size;
22 | auto pixel_data = bmp_read_pixel_data(stream, header.offset, &dib_header, &buffer_size);
23 | fclose(stream);
24 |
25 | if (pixel_data)
26 | {
27 | GifWriter gif_writer;
28 | GifBegin(&gif_writer, gifname, dib_header.width, dib_header.height, 500);
29 | GifWriteFrame(&gif_writer, (const uint8_t*)pixel_data, dib_header.width, dib_header.height, 500);
30 | GifEnd(&gif_writer);
31 | }
32 | }
33 | }
34 |
35 | printf("Gif generator finished.\n");
36 | getchar();
37 | return 0;
38 | }
--------------------------------------------------------------------------------
/GifGenerator/未命名绘图.drawio.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brookicv/Sample/1befa744304038ee5c5035a5dc9bd2093b419649/GifGenerator/未命名绘图.drawio.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | ## 项目说明
3 |
4 | - Concurrence 使用C++11 多线程库的一些例子。
5 | - 实现了一个线程安全的队列 Date:2016-10-08
6 |
7 | - GifGenerator 使用多张bitmap图像生成Gif动画 Date:2016-9-28
8 |
9 | - SoundTouch 开源库SoundTouch的Visual Studio 2013版
10 |
11 | - wav_sound 使用FFmpeg的音频处理。
12 | - 将视频中的音频提取出来,并且保存为WAV文件。 Date:2016-10-21
13 | - 使用SoundTouch库对音频进行变调、变声处理。 Date:2016-10-26
--------------------------------------------------------------------------------
/Sample.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.40629.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GifGenerator", "GifGenerator\GifGenerator.vcxproj", "{0E87164D-B996-4526-A5A6-E6C9249248E4}"
7 | EndProject
8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Concurrence", "Concurrence\Concurrence.vcxproj", "{C00DFD7A-3897-4682-9640-8D6BF131AE35}"
9 | EndProject
10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wav_sound", "wav_sound\wav_sound.vcxproj", "{0466CAD9-52B6-4F1C-85C7-AD43294B4C93}"
11 | EndProject
12 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SoundTouch", "SoundTouch\SoundTouch.vcxproj", "{32C0FBB2-32C4-452C-9971-8C21791CDB63}"
13 | EndProject
14 | Global
15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 | Debug|Win32 = Debug|Win32
17 | Release|Win32 = Release|Win32
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {0E87164D-B996-4526-A5A6-E6C9249248E4}.Debug|Win32.ActiveCfg = Debug|Win32
21 | {0E87164D-B996-4526-A5A6-E6C9249248E4}.Debug|Win32.Build.0 = Debug|Win32
22 | {0E87164D-B996-4526-A5A6-E6C9249248E4}.Release|Win32.ActiveCfg = Release|Win32
23 | {0E87164D-B996-4526-A5A6-E6C9249248E4}.Release|Win32.Build.0 = Release|Win32
24 | {C00DFD7A-3897-4682-9640-8D6BF131AE35}.Debug|Win32.ActiveCfg = Debug|Win32
25 | {C00DFD7A-3897-4682-9640-8D6BF131AE35}.Debug|Win32.Build.0 = Debug|Win32
26 | {C00DFD7A-3897-4682-9640-8D6BF131AE35}.Release|Win32.ActiveCfg = Release|Win32
27 | {C00DFD7A-3897-4682-9640-8D6BF131AE35}.Release|Win32.Build.0 = Release|Win32
28 | {0466CAD9-52B6-4F1C-85C7-AD43294B4C93}.Debug|Win32.ActiveCfg = Debug|Win32
29 | {0466CAD9-52B6-4F1C-85C7-AD43294B4C93}.Debug|Win32.Build.0 = Debug|Win32
30 | {0466CAD9-52B6-4F1C-85C7-AD43294B4C93}.Release|Win32.ActiveCfg = Release|Win32
31 | {0466CAD9-52B6-4F1C-85C7-AD43294B4C93}.Release|Win32.Build.0 = Release|Win32
32 | {32C0FBB2-32C4-452C-9971-8C21791CDB63}.Debug|Win32.ActiveCfg = Debug|Win32
33 | {32C0FBB2-32C4-452C-9971-8C21791CDB63}.Debug|Win32.Build.0 = Debug|Win32
34 | {32C0FBB2-32C4-452C-9971-8C21791CDB63}.Release|Win32.ActiveCfg = Release|Win32
35 | {32C0FBB2-32C4-452C-9971-8C21791CDB63}.Release|Win32.Build.0 = Release|Win32
36 | EndGlobalSection
37 | GlobalSection(SolutionProperties) = preSolution
38 | HideSolutionNode = FALSE
39 | EndGlobalSection
40 | EndGlobal
41 |
--------------------------------------------------------------------------------
/SoundTouch/AAFilter.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// FIR low-pass (anti-alias) filter with filter coefficient design routine and
4 | /// MMX optimization.
5 | ///
6 | /// Anti-alias filter is used to prevent folding of high frequencies when
7 | /// transposing the sample rate with interpolation.
8 | ///
9 | /// Author : Copyright (c) Olli Parviainen
10 | /// Author e-mail : oparviai 'at' iki.fi
11 | /// SoundTouch WWW: http://www.surina.net/soundtouch
12 | ///
13 | ////////////////////////////////////////////////////////////////////////////////
14 | //
15 | // Last changed : $Date: 2014-01-05 23:40:22 +0200 (Sun, 05 Jan 2014) $
16 | // File revision : $Revision: 4 $
17 | //
18 | // $Id: AAFilter.cpp 177 2014-01-05 21:40:22Z oparviai $
19 | //
20 | ////////////////////////////////////////////////////////////////////////////////
21 | //
22 | // License :
23 | //
24 | // SoundTouch audio processing library
25 | // Copyright (c) Olli Parviainen
26 | //
27 | // This library is free software; you can redistribute it and/or
28 | // modify it under the terms of the GNU Lesser General Public
29 | // License as published by the Free Software Foundation; either
30 | // version 2.1 of the License, or (at your option) any later version.
31 | //
32 | // This library is distributed in the hope that it will be useful,
33 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
34 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
35 | // Lesser General Public License for more details.
36 | //
37 | // You should have received a copy of the GNU Lesser General Public
38 | // License along with this library; if not, write to the Free Software
39 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
40 | //
41 | ////////////////////////////////////////////////////////////////////////////////
42 |
43 | #include
44 | #include
45 | #include
46 | #include
47 | #include "AAFilter.h"
48 | #include "FIRFilter.h"
49 |
50 | using namespace soundtouch;
51 |
52 | #define PI 3.141592655357989
53 | #define TWOPI (2 * PI)
54 |
55 | // define this to save AA filter coefficients to a file
56 | // #define _DEBUG_SAVE_AAFILTER_COEFFICIENTS 1
57 |
58 | #ifdef _DEBUG_SAVE_AAFILTER_COEFFICIENTS
59 | #include
60 |
61 | static void _DEBUG_SAVE_AAFIR_COEFFS(SAMPLETYPE *coeffs, int len)
62 | {
63 | FILE *fptr = fopen("aa_filter_coeffs.txt", "wt");
64 | if (fptr == NULL) return;
65 |
66 | for (int i = 0; i < len; i ++)
67 | {
68 | double temp = coeffs[i];
69 | fprintf(fptr, "%lf\n", temp);
70 | }
71 | fclose(fptr);
72 | }
73 |
74 | #else
75 | #define _DEBUG_SAVE_AAFIR_COEFFS(x, y)
76 | #endif
77 |
78 |
79 | /*****************************************************************************
80 | *
81 | * Implementation of the class 'AAFilter'
82 | *
83 | *****************************************************************************/
84 |
85 | AAFilter::AAFilter(uint len)
86 | {
87 | pFIR = FIRFilter::newInstance();
88 | cutoffFreq = 0.5;
89 | setLength(len);
90 | }
91 |
92 |
93 |
94 | AAFilter::~AAFilter()
95 | {
96 | delete pFIR;
97 | }
98 |
99 |
100 |
101 | // Sets new anti-alias filter cut-off edge frequency, scaled to
102 | // sampling frequency (nyquist frequency = 0.5).
103 | // The filter will cut frequencies higher than the given frequency.
104 | void AAFilter::setCutoffFreq(double newCutoffFreq)
105 | {
106 | cutoffFreq = newCutoffFreq;
107 | calculateCoeffs();
108 | }
109 |
110 |
111 |
112 | // Sets number of FIR filter taps
113 | void AAFilter::setLength(uint newLength)
114 | {
115 | length = newLength;
116 | calculateCoeffs();
117 | }
118 |
119 |
120 |
121 | // Calculates coefficients for a low-pass FIR filter using Hamming window
122 | void AAFilter::calculateCoeffs()
123 | {
124 | uint i;
125 | double cntTemp, temp, tempCoeff,h, w;
126 | double wc;
127 | double scaleCoeff, sum;
128 | double *work;
129 | SAMPLETYPE *coeffs;
130 |
131 | assert(length >= 2);
132 | assert(length % 4 == 0);
133 | assert(cutoffFreq >= 0);
134 | assert(cutoffFreq <= 0.5);
135 |
136 | work = new double[length];
137 | coeffs = new SAMPLETYPE[length];
138 |
139 | wc = 2.0 * PI * cutoffFreq;
140 | tempCoeff = TWOPI / (double)length;
141 |
142 | sum = 0;
143 | for (i = 0; i < length; i ++)
144 | {
145 | cntTemp = (double)i - (double)(length / 2);
146 |
147 | temp = cntTemp * wc;
148 | if (temp != 0)
149 | {
150 | h = sin(temp) / temp; // sinc function
151 | }
152 | else
153 | {
154 | h = 1.0;
155 | }
156 | w = 0.54 + 0.46 * cos(tempCoeff * cntTemp); // hamming window
157 |
158 | temp = w * h;
159 | work[i] = temp;
160 |
161 | // calc net sum of coefficients
162 | sum += temp;
163 | }
164 |
165 | // ensure the sum of coefficients is larger than zero
166 | assert(sum > 0);
167 |
168 | // ensure we've really designed a lowpass filter...
169 | assert(work[length/2] > 0);
170 | assert(work[length/2 + 1] > -1e-6);
171 | assert(work[length/2 - 1] > -1e-6);
172 |
173 | // Calculate a scaling coefficient in such a way that the result can be
174 | // divided by 16384
175 | scaleCoeff = 16384.0f / sum;
176 |
177 | for (i = 0; i < length; i ++)
178 | {
179 | temp = work[i] * scaleCoeff;
180 | //#if SOUNDTOUCH_INTEGER_SAMPLES
181 | // scale & round to nearest integer
182 | temp += (temp >= 0) ? 0.5 : -0.5;
183 | // ensure no overfloods
184 | assert(temp >= -32768 && temp <= 32767);
185 | //#endif
186 | coeffs[i] = (SAMPLETYPE)temp;
187 | }
188 |
189 | // Set coefficients. Use divide factor 14 => divide result by 2^14 = 16384
190 | pFIR->setCoefficients(coeffs, length, 14);
191 |
192 | _DEBUG_SAVE_AAFIR_COEFFS(coeffs, length);
193 |
194 | delete[] work;
195 | delete[] coeffs;
196 | }
197 |
198 |
199 | // Applies the filter to the given sequence of samples.
200 | // Note : The amount of outputted samples is by value of 'filter length'
201 | // smaller than the amount of input samples.
202 | uint AAFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels) const
203 | {
204 | return pFIR->evaluate(dest, src, numSamples, numChannels);
205 | }
206 |
207 |
208 | /// Applies the filter to the given src & dest pipes, so that processed amount of
209 | /// samples get removed from src, and produced amount added to dest
210 | /// Note : The amount of outputted samples is by value of 'filter length'
211 | /// smaller than the amount of input samples.
212 | uint AAFilter::evaluate(FIFOSampleBuffer &dest, FIFOSampleBuffer &src) const
213 | {
214 | SAMPLETYPE *pdest;
215 | const SAMPLETYPE *psrc;
216 | uint numSrcSamples;
217 | uint result;
218 | int numChannels = src.getChannels();
219 |
220 | assert(numChannels == dest.getChannels());
221 |
222 | numSrcSamples = src.numSamples();
223 | psrc = src.ptrBegin();
224 | pdest = dest.ptrEnd(numSrcSamples);
225 | result = pFIR->evaluate(pdest, psrc, numSrcSamples, numChannels);
226 | src.receiveSamples(result);
227 | dest.putSamples(result);
228 |
229 | return result;
230 | }
231 |
232 |
233 | uint AAFilter::getLength() const
234 | {
235 | return pFIR->getLength();
236 | }
237 |
--------------------------------------------------------------------------------
/SoundTouch/AAFilter.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo
4 | /// while maintaining the original pitch by using a time domain WSOLA-like method
5 | /// with several performance-increasing tweaks.
6 | ///
7 | /// Anti-alias filter is used to prevent folding of high frequencies when
8 | /// transposing the sample rate with interpolation.
9 | ///
10 | /// Author : Copyright (c) Olli Parviainen
11 | /// Author e-mail : oparviai 'at' iki.fi
12 | /// SoundTouch WWW: http://www.surina.net/soundtouch
13 | ///
14 | ////////////////////////////////////////////////////////////////////////////////
15 | //
16 | // Last changed : $Date: 2014-01-07 21:41:23 +0200 (Tue, 07 Jan 2014) $
17 | // File revision : $Revision: 4 $
18 | //
19 | // $Id: AAFilter.h 187 2014-01-07 19:41:23Z oparviai $
20 | //
21 | ////////////////////////////////////////////////////////////////////////////////
22 | //
23 | // License :
24 | //
25 | // SoundTouch audio processing library
26 | // Copyright (c) Olli Parviainen
27 | //
28 | // This library is free software; you can redistribute it and/or
29 | // modify it under the terms of the GNU Lesser General Public
30 | // License as published by the Free Software Foundation; either
31 | // version 2.1 of the License, or (at your option) any later version.
32 | //
33 | // This library is distributed in the hope that it will be useful,
34 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
35 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
36 | // Lesser General Public License for more details.
37 | //
38 | // You should have received a copy of the GNU Lesser General Public
39 | // License along with this library; if not, write to the Free Software
40 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
41 | //
42 | ////////////////////////////////////////////////////////////////////////////////
43 |
44 | #ifndef AAFilter_H
45 | #define AAFilter_H
46 |
47 | #include "STTypes.h"
48 | #include "FIFOSampleBuffer.h"
49 |
50 | namespace soundtouch
51 | {
52 |
53 | class AAFilter
54 | {
55 | protected:
56 | class FIRFilter *pFIR;
57 |
58 | /// Low-pass filter cut-off frequency, negative = invalid
59 | double cutoffFreq;
60 |
61 | /// num of filter taps
62 | uint length;
63 |
64 | /// Calculate the FIR coefficients realizing the given cutoff-frequency
65 | void calculateCoeffs();
66 | public:
67 | AAFilter(uint length);
68 |
69 | ~AAFilter();
70 |
71 | /// Sets new anti-alias filter cut-off edge frequency, scaled to sampling
72 | /// frequency (nyquist frequency = 0.5). The filter will cut off the
73 | /// frequencies than that.
74 | void setCutoffFreq(double newCutoffFreq);
75 |
76 | /// Sets number of FIR filter taps, i.e. ~filter complexity
77 | void setLength(uint newLength);
78 |
79 | uint getLength() const;
80 |
81 | /// Applies the filter to the given sequence of samples.
82 | /// Note : The amount of outputted samples is by value of 'filter length'
83 | /// smaller than the amount of input samples.
84 | uint evaluate(SAMPLETYPE *dest,
85 | const SAMPLETYPE *src,
86 | uint numSamples,
87 | uint numChannels) const;
88 |
89 | /// Applies the filter to the given src & dest pipes, so that processed amount of
90 | /// samples get removed from src, and produced amount added to dest
91 | /// Note : The amount of outputted samples is by value of 'filter length'
92 | /// smaller than the amount of input samples.
93 | uint evaluate(FIFOSampleBuffer &dest,
94 | FIFOSampleBuffer &src) const;
95 |
96 | };
97 |
98 | }
99 |
100 | #endif
101 |
--------------------------------------------------------------------------------
/SoundTouch/BPMDetect.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Beats-per-minute (BPM) detection routine.
4 | ///
5 | /// The beat detection algorithm works as follows:
6 | /// - Use function 'inputSamples' to input a chunks of samples to the class for
7 | /// analysis. It's a good idea to enter a large sound file or stream in smallish
8 | /// chunks of around few kilosamples in order not to extinguish too much RAM memory.
9 | /// - Inputted sound data is decimated to approx 500 Hz to reduce calculation burden,
10 | /// which is basically ok as low (bass) frequencies mostly determine the beat rate.
11 | /// Simple averaging is used for anti-alias filtering because the resulting signal
12 | /// quality isn't of that high importance.
13 | /// - Decimated sound data is enveloped, i.e. the amplitude shape is detected by
14 | /// taking absolute value that's smoothed by sliding average. Signal levels that
15 | /// are below a couple of times the general RMS amplitude level are cut away to
16 | /// leave only notable peaks there.
17 | /// - Repeating sound patterns (e.g. beats) are detected by calculating short-term
18 | /// autocorrelation function of the enveloped signal.
19 | /// - After whole sound data file has been analyzed as above, the bpm level is
20 | /// detected by function 'getBpm' that finds the highest peak of the autocorrelation
21 | /// function, calculates it's precise location and converts this reading to bpm's.
22 | ///
23 | /// Author : Copyright (c) Olli Parviainen
24 | /// Author e-mail : oparviai 'at' iki.fi
25 | /// SoundTouch WWW: http://www.surina.net/soundtouch
26 | ///
27 | ////////////////////////////////////////////////////////////////////////////////
28 | //
29 | // Last changed : $Date: 2015-02-21 23:24:29 +0200 (Sat, 21 Feb 2015) $
30 | // File revision : $Revision: 4 $
31 | //
32 | // $Id: BPMDetect.cpp 202 2015-02-21 21:24:29Z oparviai $
33 | //
34 | ////////////////////////////////////////////////////////////////////////////////
35 | //
36 | // License :
37 | //
38 | // SoundTouch audio processing library
39 | // Copyright (c) Olli Parviainen
40 | //
41 | // This library is free software; you can redistribute it and/or
42 | // modify it under the terms of the GNU Lesser General Public
43 | // License as published by the Free Software Foundation; either
44 | // version 2.1 of the License, or (at your option) any later version.
45 | //
46 | // This library is distributed in the hope that it will be useful,
47 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
48 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
49 | // Lesser General Public License for more details.
50 | //
51 | // You should have received a copy of the GNU Lesser General Public
52 | // License along with this library; if not, write to the Free Software
53 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
54 | //
55 | ////////////////////////////////////////////////////////////////////////////////
56 |
57 | #include
58 | #include
59 | #include
60 | #include
61 | #include "FIFOSampleBuffer.h"
62 | #include "PeakFinder.h"
63 | #include "BPMDetect.h"
64 |
65 | using namespace soundtouch;
66 |
67 | #define INPUT_BLOCK_SAMPLES 2048
68 | #define DECIMATED_BLOCK_SAMPLES 256
69 |
70 | /// decay constant for calculating RMS volume sliding average approximation
71 | /// (time constant is about 10 sec)
72 | const float avgdecay = 0.99986f;
73 |
74 | /// Normalization coefficient for calculating RMS sliding average approximation.
75 | const float avgnorm = (1 - avgdecay);
76 |
77 |
78 | ////////////////////////////////////////////////////////////////////////////////
79 |
80 | // Enable following define to create bpm analysis file:
81 |
82 | // #define _CREATE_BPM_DEBUG_FILE
83 |
84 | #ifdef _CREATE_BPM_DEBUG_FILE
85 |
86 | #define DEBUGFILE_NAME "c:\\temp\\soundtouch-bpm-debug.txt"
87 |
88 | static void _SaveDebugData(const float *data, int minpos, int maxpos, double coeff)
89 | {
90 | FILE *fptr = fopen(DEBUGFILE_NAME, "wt");
91 | int i;
92 |
93 | if (fptr)
94 | {
95 | printf("\n\nWriting BPM debug data into file " DEBUGFILE_NAME "\n\n");
96 | for (i = minpos; i < maxpos; i ++)
97 | {
98 | fprintf(fptr, "%d\t%.1lf\t%f\n", i, coeff / (double)i, data[i]);
99 | }
100 | fclose(fptr);
101 | }
102 | }
103 | #else
104 | #define _SaveDebugData(a,b,c,d)
105 | #endif
106 |
107 | ////////////////////////////////////////////////////////////////////////////////
108 |
109 |
110 | BPMDetect::BPMDetect(int numChannels, int aSampleRate)
111 | {
112 | this->sampleRate = aSampleRate;
113 | this->channels = numChannels;
114 |
115 | decimateSum = 0;
116 | decimateCount = 0;
117 |
118 | envelopeAccu = 0;
119 |
120 | // Initialize RMS volume accumulator to RMS level of 1500 (out of 32768) that's
121 | // safe initial RMS signal level value for song data. This value is then adapted
122 | // to the actual level during processing.
123 | #ifdef SOUNDTOUCH_INTEGER_SAMPLES
124 | // integer samples
125 | RMSVolumeAccu = (1500 * 1500) / avgnorm;
126 | #else
127 | // float samples, scaled to range [-1..+1[
128 | RMSVolumeAccu = (0.045f * 0.045f) / avgnorm;
129 | #endif
130 |
131 | // choose decimation factor so that result is approx. 1000 Hz
132 | decimateBy = sampleRate / 1000;
133 | assert(decimateBy > 0);
134 | assert(INPUT_BLOCK_SAMPLES < decimateBy * DECIMATED_BLOCK_SAMPLES);
135 |
136 | // Calculate window length & starting item according to desired min & max bpms
137 | windowLen = (60 * sampleRate) / (decimateBy * MIN_BPM);
138 | windowStart = (60 * sampleRate) / (decimateBy * MAX_BPM);
139 |
140 | assert(windowLen > windowStart);
141 |
142 | // allocate new working objects
143 | xcorr = new float[windowLen];
144 | memset(xcorr, 0, windowLen * sizeof(float));
145 |
146 | // allocate processing buffer
147 | buffer = new FIFOSampleBuffer();
148 | // we do processing in mono mode
149 | buffer->setChannels(1);
150 | buffer->clear();
151 | }
152 |
153 |
154 |
155 | BPMDetect::~BPMDetect()
156 | {
157 | delete[] xcorr;
158 | delete buffer;
159 | }
160 |
161 |
162 |
163 | /// convert to mono, low-pass filter & decimate to about 500 Hz.
164 | /// return number of outputted samples.
165 | ///
166 | /// Decimation is used to remove the unnecessary frequencies and thus to reduce
167 | /// the amount of data needed to be processed as calculating autocorrelation
168 | /// function is a very-very heavy operation.
169 | ///
170 | /// Anti-alias filtering is done simply by averaging the samples. This is really a
171 | /// poor-man's anti-alias filtering, but it's not so critical in this kind of application
172 | /// (it'd also be difficult to design a high-quality filter with steep cut-off at very
173 | /// narrow band)
174 | int BPMDetect::decimate(SAMPLETYPE *dest, const SAMPLETYPE *src, int numsamples)
175 | {
176 | int count, outcount;
177 | LONG_SAMPLETYPE out;
178 |
179 | assert(channels > 0);
180 | assert(decimateBy > 0);
181 | outcount = 0;
182 | for (count = 0; count < numsamples; count ++)
183 | {
184 | int j;
185 |
186 | // convert to mono and accumulate
187 | for (j = 0; j < channels; j ++)
188 | {
189 | decimateSum += src[j];
190 | }
191 | src += j;
192 |
193 | decimateCount ++;
194 | if (decimateCount >= decimateBy)
195 | {
196 | // Store every Nth sample only
197 | out = (LONG_SAMPLETYPE)(decimateSum / (decimateBy * channels));
198 | decimateSum = 0;
199 | decimateCount = 0;
200 | #ifdef SOUNDTOUCH_INTEGER_SAMPLES
201 | // check ranges for sure (shouldn't actually be necessary)
202 | if (out > 32767)
203 | {
204 | out = 32767;
205 | }
206 | else if (out < -32768)
207 | {
208 | out = -32768;
209 | }
210 | #endif // SOUNDTOUCH_INTEGER_SAMPLES
211 | dest[outcount] = (SAMPLETYPE)out;
212 | outcount ++;
213 | }
214 | }
215 | return outcount;
216 | }
217 |
218 |
219 |
220 | // Calculates autocorrelation function of the sample history buffer
221 | void BPMDetect::updateXCorr(int process_samples)
222 | {
223 | int offs;
224 | SAMPLETYPE *pBuffer;
225 |
226 | assert(buffer->numSamples() >= (uint)(process_samples + windowLen));
227 |
228 | pBuffer = buffer->ptrBegin();
229 | #pragma omp parallel for
230 | for (offs = windowStart; offs < windowLen; offs ++)
231 | {
232 | LONG_SAMPLETYPE sum;
233 | int i;
234 |
235 | sum = 0;
236 | for (i = 0; i < process_samples; i ++)
237 | {
238 | sum += pBuffer[i] * pBuffer[i + offs]; // scaling the sub-result shouldn't be necessary
239 | }
240 | // xcorr[offs] *= xcorr_decay; // decay 'xcorr' here with suitable coefficients
241 | // if it's desired that the system adapts automatically to
242 | // various bpms, e.g. in processing continouos music stream.
243 | // The 'xcorr_decay' should be a value that's smaller than but
244 | // close to one, and should also depend on 'process_samples' value.
245 |
246 | xcorr[offs] += (float)sum;
247 | }
248 | }
249 |
250 |
251 | // Calculates envelope of the sample data
252 | void BPMDetect::calcEnvelope(SAMPLETYPE *samples, int numsamples)
253 | {
254 | const static double decay = 0.7f; // decay constant for smoothing the envelope
255 | const static double norm = (1 - decay);
256 |
257 | int i;
258 | LONG_SAMPLETYPE out;
259 | double val;
260 |
261 | for (i = 0; i < numsamples; i ++)
262 | {
263 | // calc average RMS volume
264 | RMSVolumeAccu *= avgdecay;
265 | val = (float)fabs((float)samples[i]);
266 | RMSVolumeAccu += val * val;
267 |
268 | // cut amplitudes that are below cutoff ~2 times RMS volume
269 | // (we're interested in peak values, not the silent moments)
270 | if (val < 0.5 * sqrt(RMSVolumeAccu * avgnorm))
271 | {
272 | val = 0;
273 | }
274 |
275 | // smooth amplitude envelope
276 | envelopeAccu *= decay;
277 | envelopeAccu += val;
278 | out = (LONG_SAMPLETYPE)(envelopeAccu * norm);
279 |
280 | #ifdef SOUNDTOUCH_INTEGER_SAMPLES
281 | // cut peaks (shouldn't be necessary though)
282 | if (out > 32767) out = 32767;
283 | #endif // SOUNDTOUCH_INTEGER_SAMPLES
284 | samples[i] = (SAMPLETYPE)out;
285 | }
286 | }
287 |
288 |
289 |
290 | void BPMDetect::inputSamples(const SAMPLETYPE *samples, int numSamples)
291 | {
292 | SAMPLETYPE decimated[DECIMATED_BLOCK_SAMPLES];
293 |
294 | // iterate so that max INPUT_BLOCK_SAMPLES processed per iteration
295 | while (numSamples > 0)
296 | {
297 | int block;
298 | int decSamples;
299 |
300 | block = (numSamples > INPUT_BLOCK_SAMPLES) ? INPUT_BLOCK_SAMPLES : numSamples;
301 |
302 | // decimate. note that converts to mono at the same time
303 | decSamples = decimate(decimated, samples, block);
304 | samples += block * channels;
305 | numSamples -= block;
306 |
307 | // envelope new samples and add them to buffer
308 | calcEnvelope(decimated, decSamples);
309 | buffer->putSamples(decimated, decSamples);
310 | }
311 |
312 | // when the buffer has enought samples for processing...
313 | if ((int)buffer->numSamples() > windowLen)
314 | {
315 | int processLength;
316 |
317 | // how many samples are processed
318 | processLength = (int)buffer->numSamples() - windowLen;
319 |
320 | // ... calculate autocorrelations for oldest samples...
321 | updateXCorr(processLength);
322 | // ... and remove them from the buffer
323 | buffer->receiveSamples(processLength);
324 | }
325 | }
326 |
327 |
328 |
329 | void BPMDetect::removeBias()
330 | {
331 | int i;
332 | float minval = 1e12f; // arbitrary large number
333 |
334 | for (i = windowStart; i < windowLen; i ++)
335 | {
336 | if (xcorr[i] < minval)
337 | {
338 | minval = xcorr[i];
339 | }
340 | }
341 |
342 | for (i = windowStart; i < windowLen; i ++)
343 | {
344 | xcorr[i] -= minval;
345 | }
346 | }
347 |
348 |
349 | float BPMDetect::getBpm()
350 | {
351 | double peakPos;
352 | double coeff;
353 | PeakFinder peakFinder;
354 |
355 | coeff = 60.0 * ((double)sampleRate / (double)decimateBy);
356 |
357 | // save bpm debug analysis data if debug data enabled
358 | _SaveDebugData(xcorr, windowStart, windowLen, coeff);
359 |
360 | // remove bias from xcorr data
361 | removeBias();
362 |
363 | // find peak position
364 | peakPos = peakFinder.detectPeak(xcorr, windowStart, windowLen);
365 |
366 | assert(decimateBy != 0);
367 | if (peakPos < 1e-9) return 0.0; // detection failed.
368 |
369 | // calculate BPM
370 | return (float) (coeff / peakPos);
371 | }
372 |
--------------------------------------------------------------------------------
/SoundTouch/BPMDetect.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Beats-per-minute (BPM) detection routine.
4 | ///
5 | /// The beat detection algorithm works as follows:
6 | /// - Use function 'inputSamples' to input a chunks of samples to the class for
7 | /// analysis. It's a good idea to enter a large sound file or stream in smallish
8 | /// chunks of around few kilosamples in order not to extinguish too much RAM memory.
9 | /// - Input sound data is decimated to approx 500 Hz to reduce calculation burden,
10 | /// which is basically ok as low (bass) frequencies mostly determine the beat rate.
11 | /// Simple averaging is used for anti-alias filtering because the resulting signal
12 | /// quality isn't of that high importance.
13 | /// - Decimated sound data is enveloped, i.e. the amplitude shape is detected by
14 | /// taking absolute value that's smoothed by sliding average. Signal levels that
15 | /// are below a couple of times the general RMS amplitude level are cut away to
16 | /// leave only notable peaks there.
17 | /// - Repeating sound patterns (e.g. beats) are detected by calculating short-term
18 | /// autocorrelation function of the enveloped signal.
19 | /// - After whole sound data file has been analyzed as above, the bpm level is
20 | /// detected by function 'getBpm' that finds the highest peak of the autocorrelation
21 | /// function, calculates it's precise location and converts this reading to bpm's.
22 | ///
23 | /// Author : Copyright (c) Olli Parviainen
24 | /// Author e-mail : oparviai 'at' iki.fi
25 | /// SoundTouch WWW: http://www.surina.net/soundtouch
26 | ///
27 | ////////////////////////////////////////////////////////////////////////////////
28 | //
29 | // Last changed : $Date: 2012-08-30 22:53:44 +0300 (Thu, 30 Aug 2012) $
30 | // File revision : $Revision: 4 $
31 | //
32 | // $Id: BPMDetect.h 150 2012-08-30 19:53:44Z oparviai $
33 | //
34 | ////////////////////////////////////////////////////////////////////////////////
35 | //
36 | // License :
37 | //
38 | // SoundTouch audio processing library
39 | // Copyright (c) Olli Parviainen
40 | //
41 | // This library is free software; you can redistribute it and/or
42 | // modify it under the terms of the GNU Lesser General Public
43 | // License as published by the Free Software Foundation; either
44 | // version 2.1 of the License, or (at your option) any later version.
45 | //
46 | // This library is distributed in the hope that it will be useful,
47 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
48 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
49 | // Lesser General Public License for more details.
50 | //
51 | // You should have received a copy of the GNU Lesser General Public
52 | // License along with this library; if not, write to the Free Software
53 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
54 | //
55 | ////////////////////////////////////////////////////////////////////////////////
56 |
57 | #ifndef _BPMDetect_H_
58 | #define _BPMDetect_H_
59 |
60 | #include "STTypes.h"
61 | #include "FIFOSampleBuffer.h"
62 |
63 | namespace soundtouch
64 | {
65 |
66 | /// Minimum allowed BPM rate. Used to restrict accepted result above a reasonable limit.
67 | #define MIN_BPM 29
68 |
69 | /// Maximum allowed BPM rate. Used to restrict accepted result below a reasonable limit.
70 | #define MAX_BPM 200
71 |
72 |
73 | /// Class for calculating BPM rate for audio data.
74 | class BPMDetect
75 | {
76 | protected:
77 | /// Auto-correlation accumulator bins.
78 | float *xcorr;
79 |
80 | /// Amplitude envelope sliding average approximation level accumulator
81 | double envelopeAccu;
82 |
83 | /// RMS volume sliding average approximation level accumulator
84 | double RMSVolumeAccu;
85 |
86 | /// Sample average counter.
87 | int decimateCount;
88 |
89 | /// Sample average accumulator for FIFO-like decimation.
90 | soundtouch::LONG_SAMPLETYPE decimateSum;
91 |
92 | /// Decimate sound by this coefficient to reach approx. 500 Hz.
93 | int decimateBy;
94 |
95 | /// Auto-correlation window length
96 | int windowLen;
97 |
98 | /// Number of channels (1 = mono, 2 = stereo)
99 | int channels;
100 |
101 | /// sample rate
102 | int sampleRate;
103 |
104 | /// Beginning of auto-correlation window: Autocorrelation isn't being updated for
105 | /// the first these many correlation bins.
106 | int windowStart;
107 |
108 | /// FIFO-buffer for decimated processing samples.
109 | soundtouch::FIFOSampleBuffer *buffer;
110 |
111 | /// Updates auto-correlation function for given number of decimated samples that
112 | /// are read from the internal 'buffer' pipe (samples aren't removed from the pipe
113 | /// though).
114 | void updateXCorr(int process_samples /// How many samples are processed.
115 | );
116 |
117 | /// Decimates samples to approx. 500 Hz.
118 | ///
119 | /// \return Number of output samples.
120 | int decimate(soundtouch::SAMPLETYPE *dest, ///< Destination buffer
121 | const soundtouch::SAMPLETYPE *src, ///< Source sample buffer
122 | int numsamples ///< Number of source samples.
123 | );
124 |
125 | /// Calculates amplitude envelope for the buffer of samples.
126 | /// Result is output to 'samples'.
127 | void calcEnvelope(soundtouch::SAMPLETYPE *samples, ///< Pointer to input/output data buffer
128 | int numsamples ///< Number of samples in buffer
129 | );
130 |
131 | /// remove constant bias from xcorr data
132 | void removeBias();
133 |
134 | public:
135 | /// Constructor.
136 | BPMDetect(int numChannels, ///< Number of channels in sample data.
137 | int sampleRate ///< Sample rate in Hz.
138 | );
139 |
140 | /// Destructor.
141 | virtual ~BPMDetect();
142 |
143 | /// Inputs a block of samples for analyzing: Envelopes the samples and then
144 | /// updates the autocorrelation estimation. When whole song data has been input
145 | /// in smaller blocks using this function, read the resulting bpm with 'getBpm'
146 | /// function.
147 | ///
148 | /// Notice that data in 'samples' array can be disrupted in processing.
149 | void inputSamples(const soundtouch::SAMPLETYPE *samples, ///< Pointer to input/working data buffer
150 | int numSamples ///< Number of samples in buffer
151 | );
152 |
153 |
154 | /// Analyzes the results and returns the BPM rate. Use this function to read result
155 | /// after whole song data has been input to the class by consecutive calls of
156 | /// 'inputSamples' function.
157 | ///
158 | /// \return Beats-per-minute rate, or zero if detection failed.
159 | float getBpm();
160 | };
161 |
162 | }
163 |
164 | #endif // _BPMDetect_H_
165 |
--------------------------------------------------------------------------------
/SoundTouch/FIFOSampleBuffer.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// A buffer class for temporarily storaging sound samples, operates as a
4 | /// first-in-first-out pipe.
5 | ///
6 | /// Samples are added to the end of the sample buffer with the 'putSamples'
7 | /// function, and are received from the beginning of the buffer by calling
8 | /// the 'receiveSamples' function. The class automatically removes the
9 | /// outputted samples from the buffer, as well as grows the buffer size
10 | /// whenever necessary.
11 | ///
12 | /// Author : Copyright (c) Olli Parviainen
13 | /// Author e-mail : oparviai 'at' iki.fi
14 | /// SoundTouch WWW: http://www.surina.net/soundtouch
15 | ///
16 | ////////////////////////////////////////////////////////////////////////////////
17 | //
18 | // Last changed : $Date: 2012-11-08 20:53:01 +0200 (Thu, 08 Nov 2012) $
19 | // File revision : $Revision: 4 $
20 | //
21 | // $Id: FIFOSampleBuffer.cpp 160 2012-11-08 18:53:01Z oparviai $
22 | //
23 | ////////////////////////////////////////////////////////////////////////////////
24 | //
25 | // License :
26 | //
27 | // SoundTouch audio processing library
28 | // Copyright (c) Olli Parviainen
29 | //
30 | // This library is free software; you can redistribute it and/or
31 | // modify it under the terms of the GNU Lesser General Public
32 | // License as published by the Free Software Foundation; either
33 | // version 2.1 of the License, or (at your option) any later version.
34 | //
35 | // This library is distributed in the hope that it will be useful,
36 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
37 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
38 | // Lesser General Public License for more details.
39 | //
40 | // You should have received a copy of the GNU Lesser General Public
41 | // License along with this library; if not, write to the Free Software
42 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
43 | //
44 | ////////////////////////////////////////////////////////////////////////////////
45 |
46 | #include
47 | #include
48 | #include
49 | #include
50 |
51 | #include "FIFOSampleBuffer.h"
52 |
53 | using namespace soundtouch;
54 |
55 | // Constructor
56 | FIFOSampleBuffer::FIFOSampleBuffer(int numChannels)
57 | {
58 | assert(numChannels > 0);
59 | sizeInBytes = 0; // reasonable initial value
60 | buffer = NULL;
61 | bufferUnaligned = NULL;
62 | samplesInBuffer = 0;
63 | bufferPos = 0;
64 | channels = (uint)numChannels;
65 | ensureCapacity(32); // allocate initial capacity
66 | }
67 |
68 |
69 | // destructor
70 | FIFOSampleBuffer::~FIFOSampleBuffer()
71 | {
72 | delete[] bufferUnaligned;
73 | bufferUnaligned = NULL;
74 | buffer = NULL;
75 | }
76 |
77 |
78 | // Sets number of channels, 1 = mono, 2 = stereo
79 | void FIFOSampleBuffer::setChannels(int numChannels)
80 | {
81 | uint usedBytes;
82 |
83 | assert(numChannels > 0);
84 | usedBytes = channels * samplesInBuffer;
85 | channels = (uint)numChannels;
86 | samplesInBuffer = usedBytes / channels;
87 | }
88 |
89 |
90 | // if output location pointer 'bufferPos' isn't zero, 'rewinds' the buffer and
91 | // zeroes this pointer by copying samples from the 'bufferPos' pointer
92 | // location on to the beginning of the buffer.
93 | void FIFOSampleBuffer::rewind()
94 | {
95 | if (buffer && bufferPos)
96 | {
97 | memmove(buffer, ptrBegin(), sizeof(SAMPLETYPE) * channels * samplesInBuffer);
98 | bufferPos = 0;
99 | }
100 | }
101 |
102 |
103 | // Adds 'numSamples' pcs of samples from the 'samples' memory position to
104 | // the sample buffer.
105 | void FIFOSampleBuffer::putSamples(const SAMPLETYPE *samples, uint nSamples)
106 | {
107 | memcpy(ptrEnd(nSamples), samples, sizeof(SAMPLETYPE) * nSamples * channels);
108 | samplesInBuffer += nSamples;
109 | }
110 |
111 |
112 | // Increases the number of samples in the buffer without copying any actual
113 | // samples.
114 | //
115 | // This function is used to update the number of samples in the sample buffer
116 | // when accessing the buffer directly with 'ptrEnd' function. Please be
117 | // careful though!
118 | void FIFOSampleBuffer::putSamples(uint nSamples)
119 | {
120 | uint req;
121 |
122 | req = samplesInBuffer + nSamples;
123 | ensureCapacity(req);
124 | samplesInBuffer += nSamples;
125 | }
126 |
127 |
128 | // Returns a pointer to the end of the used part of the sample buffer (i.e.
129 | // where the new samples are to be inserted). This function may be used for
130 | // inserting new samples into the sample buffer directly. Please be careful!
131 | //
132 | // Parameter 'slackCapacity' tells the function how much free capacity (in
133 | // terms of samples) there _at least_ should be, in order to the caller to
134 | // succesfully insert all the required samples to the buffer. When necessary,
135 | // the function grows the buffer size to comply with this requirement.
136 | //
137 | // When using this function as means for inserting new samples, also remember
138 | // to increase the sample count afterwards, by calling the
139 | // 'putSamples(numSamples)' function.
140 | SAMPLETYPE *FIFOSampleBuffer::ptrEnd(uint slackCapacity)
141 | {
142 | ensureCapacity(samplesInBuffer + slackCapacity);
143 | return buffer + samplesInBuffer * channels;
144 | }
145 |
146 |
147 | // Returns a pointer to the beginning of the currently non-outputted samples.
148 | // This function is provided for accessing the output samples directly.
149 | // Please be careful!
150 | //
151 | // When using this function to output samples, also remember to 'remove' the
152 | // outputted samples from the buffer by calling the
153 | // 'receiveSamples(numSamples)' function
154 | SAMPLETYPE *FIFOSampleBuffer::ptrBegin()
155 | {
156 | assert(buffer);
157 | return buffer + bufferPos * channels;
158 | }
159 |
160 |
161 | // Ensures that the buffer has enought capacity, i.e. space for _at least_
162 | // 'capacityRequirement' number of samples. The buffer is grown in steps of
163 | // 4 kilobytes to eliminate the need for frequently growing up the buffer,
164 | // as well as to round the buffer size up to the virtual memory page size.
165 | void FIFOSampleBuffer::ensureCapacity(uint capacityRequirement)
166 | {
167 | SAMPLETYPE *tempUnaligned, *temp;
168 |
169 | if (capacityRequirement > getCapacity())
170 | {
171 | // enlarge the buffer in 4kbyte steps (round up to next 4k boundary)
172 | sizeInBytes = (capacityRequirement * channels * sizeof(SAMPLETYPE) + 4095) & (uint)-4096;
173 | assert(sizeInBytes % 2 == 0);
174 | tempUnaligned = new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE) + 16 / sizeof(SAMPLETYPE)];
175 | if (tempUnaligned == NULL)
176 | {
177 | ST_THROW_RT_ERROR("Couldn't allocate memory!\n");
178 | }
179 | // Align the buffer to begin at 16byte cache line boundary for optimal performance
180 | temp = (SAMPLETYPE *)SOUNDTOUCH_ALIGN_POINTER_16(tempUnaligned);
181 | if (samplesInBuffer)
182 | {
183 | memcpy(temp, ptrBegin(), samplesInBuffer * channels * sizeof(SAMPLETYPE));
184 | }
185 | delete[] bufferUnaligned;
186 | buffer = temp;
187 | bufferUnaligned = tempUnaligned;
188 | bufferPos = 0;
189 | }
190 | else
191 | {
192 | // simply rewind the buffer (if necessary)
193 | rewind();
194 | }
195 | }
196 |
197 |
198 | // Returns the current buffer capacity in terms of samples
199 | uint FIFOSampleBuffer::getCapacity() const
200 | {
201 | return sizeInBytes / (channels * sizeof(SAMPLETYPE));
202 | }
203 |
204 |
205 | // Returns the number of samples currently in the buffer
206 | uint FIFOSampleBuffer::numSamples() const
207 | {
208 | return samplesInBuffer;
209 | }
210 |
211 |
212 | // Output samples from beginning of the sample buffer. Copies demanded number
213 | // of samples to output and removes them from the sample buffer. If there
214 | // are less than 'numsample' samples in the buffer, returns all available.
215 | //
216 | // Returns number of samples copied.
217 | uint FIFOSampleBuffer::receiveSamples(SAMPLETYPE *output, uint maxSamples)
218 | {
219 | uint num;
220 |
221 | num = (maxSamples > samplesInBuffer) ? samplesInBuffer : maxSamples;
222 |
223 | memcpy(output, ptrBegin(), channels * sizeof(SAMPLETYPE) * num);
224 | return receiveSamples(num);
225 | }
226 |
227 |
228 | // Removes samples from the beginning of the sample buffer without copying them
229 | // anywhere. Used to reduce the number of samples in the buffer, when accessing
230 | // the sample buffer with the 'ptrBegin' function.
231 | uint FIFOSampleBuffer::receiveSamples(uint maxSamples)
232 | {
233 | if (maxSamples >= samplesInBuffer)
234 | {
235 | uint temp;
236 |
237 | temp = samplesInBuffer;
238 | samplesInBuffer = 0;
239 | return temp;
240 | }
241 |
242 | samplesInBuffer -= maxSamples;
243 | bufferPos += maxSamples;
244 |
245 | return maxSamples;
246 | }
247 |
248 |
249 | // Returns nonzero if the sample buffer is empty
250 | int FIFOSampleBuffer::isEmpty() const
251 | {
252 | return (samplesInBuffer == 0) ? 1 : 0;
253 | }
254 |
255 |
256 | // Clears the sample buffer
257 | void FIFOSampleBuffer::clear()
258 | {
259 | samplesInBuffer = 0;
260 | bufferPos = 0;
261 | }
262 |
263 |
264 | /// allow trimming (downwards) amount of samples in pipeline.
265 | /// Returns adjusted amount of samples
266 | uint FIFOSampleBuffer::adjustAmountOfSamples(uint numSamples)
267 | {
268 | if (numSamples < samplesInBuffer)
269 | {
270 | samplesInBuffer = numSamples;
271 | }
272 | return samplesInBuffer;
273 | }
274 |
275 |
--------------------------------------------------------------------------------
/SoundTouch/FIFOSampleBuffer.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// A buffer class for temporarily storaging sound samples, operates as a
4 | /// first-in-first-out pipe.
5 | ///
6 | /// Samples are added to the end of the sample buffer with the 'putSamples'
7 | /// function, and are received from the beginning of the buffer by calling
8 | /// the 'receiveSamples' function. The class automatically removes the
9 | /// output samples from the buffer as well as grows the storage size
10 | /// whenever necessary.
11 | ///
12 | /// Author : Copyright (c) Olli Parviainen
13 | /// Author e-mail : oparviai 'at' iki.fi
14 | /// SoundTouch WWW: http://www.surina.net/soundtouch
15 | ///
16 | ////////////////////////////////////////////////////////////////////////////////
17 | //
18 | // Last changed : $Date: 2014-01-05 23:40:22 +0200 (Sun, 05 Jan 2014) $
19 | // File revision : $Revision: 4 $
20 | //
21 | // $Id: FIFOSampleBuffer.h 177 2014-01-05 21:40:22Z oparviai $
22 | //
23 | ////////////////////////////////////////////////////////////////////////////////
24 | //
25 | // License :
26 | //
27 | // SoundTouch audio processing library
28 | // Copyright (c) Olli Parviainen
29 | //
30 | // This library is free software; you can redistribute it and/or
31 | // modify it under the terms of the GNU Lesser General Public
32 | // License as published by the Free Software Foundation; either
33 | // version 2.1 of the License, or (at your option) any later version.
34 | //
35 | // This library is distributed in the hope that it will be useful,
36 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
37 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
38 | // Lesser General Public License for more details.
39 | //
40 | // You should have received a copy of the GNU Lesser General Public
41 | // License along with this library; if not, write to the Free Software
42 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
43 | //
44 | ////////////////////////////////////////////////////////////////////////////////
45 |
46 | #ifndef FIFOSampleBuffer_H
47 | #define FIFOSampleBuffer_H
48 |
49 | #include "FIFOSamplePipe.h"
50 |
51 | namespace soundtouch
52 | {
53 |
54 | /// Sample buffer working in FIFO (first-in-first-out) principle. The class takes
55 | /// care of storage size adjustment and data moving during input/output operations.
56 | ///
57 | /// Notice that in case of stereo audio, one sample is considered to consist of
58 | /// both channel data.
59 | class FIFOSampleBuffer : public FIFOSamplePipe
60 | {
61 | private:
62 | /// Sample buffer.
63 | SAMPLETYPE *buffer;
64 |
65 | // Raw unaligned buffer memory. 'buffer' is made aligned by pointing it to first
66 | // 16-byte aligned location of this buffer
67 | SAMPLETYPE *bufferUnaligned;
68 |
69 | /// Sample buffer size in bytes
70 | uint sizeInBytes;
71 |
72 | /// How many samples are currently in buffer.
73 | uint samplesInBuffer;
74 |
75 | /// Channels, 1=mono, 2=stereo.
76 | uint channels;
77 |
78 | /// Current position pointer to the buffer. This pointer is increased when samples are
79 | /// removed from the pipe so that it's necessary to actually rewind buffer (move data)
80 | /// only new data when is put to the pipe.
81 | uint bufferPos;
82 |
83 | /// Rewind the buffer by moving data from position pointed by 'bufferPos' to real
84 | /// beginning of the buffer.
85 | void rewind();
86 |
87 | /// Ensures that the buffer has capacity for at least this many samples.
88 | void ensureCapacity(uint capacityRequirement);
89 |
90 | /// Returns current capacity.
91 | uint getCapacity() const;
92 |
93 | public:
94 |
95 | /// Constructor
96 | FIFOSampleBuffer(int numChannels = 2 ///< Number of channels, 1=mono, 2=stereo.
97 | ///< Default is stereo.
98 | );
99 |
100 | /// destructor
101 | ~FIFOSampleBuffer();
102 |
103 | /// Returns a pointer to the beginning of the output samples.
104 | /// This function is provided for accessing the output samples directly.
105 | /// Please be careful for not to corrupt the book-keeping!
106 | ///
107 | /// When using this function to output samples, also remember to 'remove' the
108 | /// output samples from the buffer by calling the
109 | /// 'receiveSamples(numSamples)' function
110 | virtual SAMPLETYPE *ptrBegin();
111 |
112 | /// Returns a pointer to the end of the used part of the sample buffer (i.e.
113 | /// where the new samples are to be inserted). This function may be used for
114 | /// inserting new samples into the sample buffer directly. Please be careful
115 | /// not corrupt the book-keeping!
116 | ///
117 | /// When using this function as means for inserting new samples, also remember
118 | /// to increase the sample count afterwards, by calling the
119 | /// 'putSamples(numSamples)' function.
120 | SAMPLETYPE *ptrEnd(
121 | uint slackCapacity ///< How much free capacity (in samples) there _at least_
122 | ///< should be so that the caller can succesfully insert the
123 | ///< desired samples to the buffer. If necessary, the function
124 | ///< grows the buffer size to comply with this requirement.
125 | );
126 |
127 | /// Adds 'numSamples' pcs of samples from the 'samples' memory position to
128 | /// the sample buffer.
129 | virtual void putSamples(const SAMPLETYPE *samples, ///< Pointer to samples.
130 | uint numSamples ///< Number of samples to insert.
131 | );
132 |
133 | /// Adjusts the book-keeping to increase number of samples in the buffer without
134 | /// copying any actual samples.
135 | ///
136 | /// This function is used to update the number of samples in the sample buffer
137 | /// when accessing the buffer directly with 'ptrEnd' function. Please be
138 | /// careful though!
139 | virtual void putSamples(uint numSamples ///< Number of samples been inserted.
140 | );
141 |
142 | /// Output samples from beginning of the sample buffer. Copies requested samples to
143 | /// output buffer and removes them from the sample buffer. If there are less than
144 | /// 'numsample' samples in the buffer, returns all that available.
145 | ///
146 | /// \return Number of samples returned.
147 | virtual uint receiveSamples(SAMPLETYPE *output, ///< Buffer where to copy output samples.
148 | uint maxSamples ///< How many samples to receive at max.
149 | );
150 |
151 | /// Adjusts book-keeping so that given number of samples are removed from beginning of the
152 | /// sample buffer without copying them anywhere.
153 | ///
154 | /// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
155 | /// with 'ptrBegin' function.
156 | virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe.
157 | );
158 |
159 | /// Returns number of samples currently available.
160 | virtual uint numSamples() const;
161 |
162 | /// Sets number of channels, 1 = mono, 2 = stereo.
163 | void setChannels(int numChannels);
164 |
165 | /// Get number of channels
166 | int getChannels()
167 | {
168 | return channels;
169 | }
170 |
171 | /// Returns nonzero if there aren't any samples available for outputting.
172 | virtual int isEmpty() const;
173 |
174 | /// Clears all the samples.
175 | virtual void clear();
176 |
177 | /// allow trimming (downwards) amount of samples in pipeline.
178 | /// Returns adjusted amount of samples
179 | uint adjustAmountOfSamples(uint numSamples);
180 | };
181 |
182 | }
183 |
184 | #endif
185 |
--------------------------------------------------------------------------------
/SoundTouch/FIFOSamplePipe.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// 'FIFOSamplePipe' : An abstract base class for classes that manipulate sound
4 | /// samples by operating like a first-in-first-out pipe: New samples are fed
5 | /// into one end of the pipe with the 'putSamples' function, and the processed
6 | /// samples are received from the other end with the 'receiveSamples' function.
7 | ///
8 | /// 'FIFOProcessor' : A base class for classes the do signal processing with
9 | /// the samples while operating like a first-in-first-out pipe. When samples
10 | /// are input with the 'putSamples' function, the class processes them
11 | /// and moves the processed samples to the given 'output' pipe object, which
12 | /// may be either another processing stage, or a fifo sample buffer object.
13 | ///
14 | /// Author : Copyright (c) Olli Parviainen
15 | /// Author e-mail : oparviai 'at' iki.fi
16 | /// SoundTouch WWW: http://www.surina.net/soundtouch
17 | ///
18 | ////////////////////////////////////////////////////////////////////////////////
19 | //
20 | // Last changed : $Date: 2012-06-13 22:29:53 +0300 (Wed, 13 Jun 2012) $
21 | // File revision : $Revision: 4 $
22 | //
23 | // $Id: FIFOSamplePipe.h 143 2012-06-13 19:29:53Z oparviai $
24 | //
25 | ////////////////////////////////////////////////////////////////////////////////
26 | //
27 | // License :
28 | //
29 | // SoundTouch audio processing library
30 | // Copyright (c) Olli Parviainen
31 | //
32 | // This library is free software; you can redistribute it and/or
33 | // modify it under the terms of the GNU Lesser General Public
34 | // License as published by the Free Software Foundation; either
35 | // version 2.1 of the License, or (at your option) any later version.
36 | //
37 | // This library is distributed in the hope that it will be useful,
38 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
39 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
40 | // Lesser General Public License for more details.
41 | //
42 | // You should have received a copy of the GNU Lesser General Public
43 | // License along with this library; if not, write to the Free Software
44 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
45 | //
46 | ////////////////////////////////////////////////////////////////////////////////
47 |
48 | #ifndef FIFOSamplePipe_H
49 | #define FIFOSamplePipe_H
50 |
51 | #include
52 | #include
53 | #include "STTypes.h"
54 |
55 | namespace soundtouch
56 | {
57 |
58 | /// Abstract base class for FIFO (first-in-first-out) sample processing classes.
59 | class FIFOSamplePipe
60 | {
61 | public:
62 | // virtual default destructor
63 | virtual ~FIFOSamplePipe() {}
64 |
65 |
66 | /// Returns a pointer to the beginning of the output samples.
67 | /// This function is provided for accessing the output samples directly.
68 | /// Please be careful for not to corrupt the book-keeping!
69 | ///
70 | /// When using this function to output samples, also remember to 'remove' the
71 | /// output samples from the buffer by calling the
72 | /// 'receiveSamples(numSamples)' function
73 | virtual SAMPLETYPE *ptrBegin() = 0;
74 |
75 | /// Adds 'numSamples' pcs of samples from the 'samples' memory position to
76 | /// the sample buffer.
77 | virtual void putSamples(const SAMPLETYPE *samples, ///< Pointer to samples.
78 | uint numSamples ///< Number of samples to insert.
79 | ) = 0;
80 |
81 |
82 | // Moves samples from the 'other' pipe instance to this instance.
83 | void moveSamples(FIFOSamplePipe &other ///< Other pipe instance where from the receive the data.
84 | )
85 | {
86 | int oNumSamples = other.numSamples();
87 |
88 | putSamples(other.ptrBegin(), oNumSamples);
89 | other.receiveSamples(oNumSamples);
90 | };
91 |
92 | /// Output samples from beginning of the sample buffer. Copies requested samples to
93 | /// output buffer and removes them from the sample buffer. If there are less than
94 | /// 'numsample' samples in the buffer, returns all that available.
95 | ///
96 | /// \return Number of samples returned.
97 | virtual uint receiveSamples(SAMPLETYPE *output, ///< Buffer where to copy output samples.
98 | uint maxSamples ///< How many samples to receive at max.
99 | ) = 0;
100 |
101 | /// Adjusts book-keeping so that given number of samples are removed from beginning of the
102 | /// sample buffer without copying them anywhere.
103 | ///
104 | /// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
105 | /// with 'ptrBegin' function.
106 | virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe.
107 | ) = 0;
108 |
109 | /// Returns number of samples currently available.
110 | virtual uint numSamples() const = 0;
111 |
112 | // Returns nonzero if there aren't any samples available for outputting.
113 | virtual int isEmpty() const = 0;
114 |
115 | /// Clears all the samples.
116 | virtual void clear() = 0;
117 |
118 | /// allow trimming (downwards) amount of samples in pipeline.
119 | /// Returns adjusted amount of samples
120 | virtual uint adjustAmountOfSamples(uint numSamples) = 0;
121 |
122 | };
123 |
124 |
125 |
126 | /// Base-class for sound processing routines working in FIFO principle. With this base
127 | /// class it's easy to implement sound processing stages that can be chained together,
128 | /// so that samples that are fed into beginning of the pipe automatically go through
129 | /// all the processing stages.
130 | ///
131 | /// When samples are input to this class, they're first processed and then put to
132 | /// the FIFO pipe that's defined as output of this class. This output pipe can be
133 | /// either other processing stage or a FIFO sample buffer.
134 | class FIFOProcessor :public FIFOSamplePipe
135 | {
136 | protected:
137 | /// Internal pipe where processed samples are put.
138 | FIFOSamplePipe *output;
139 |
140 | /// Sets output pipe.
141 | void setOutPipe(FIFOSamplePipe *pOutput)
142 | {
143 | assert(output == NULL);
144 | assert(pOutput != NULL);
145 | output = pOutput;
146 | }
147 |
148 |
149 | /// Constructor. Doesn't define output pipe; it has to be set be
150 | /// 'setOutPipe' function.
151 | FIFOProcessor()
152 | {
153 | output = NULL;
154 | }
155 |
156 |
157 | /// Constructor. Configures output pipe.
158 | FIFOProcessor(FIFOSamplePipe *pOutput ///< Output pipe.
159 | )
160 | {
161 | output = pOutput;
162 | }
163 |
164 |
165 | /// Destructor.
166 | virtual ~FIFOProcessor()
167 | {
168 | }
169 |
170 |
171 | /// Returns a pointer to the beginning of the output samples.
172 | /// This function is provided for accessing the output samples directly.
173 | /// Please be careful for not to corrupt the book-keeping!
174 | ///
175 | /// When using this function to output samples, also remember to 'remove' the
176 | /// output samples from the buffer by calling the
177 | /// 'receiveSamples(numSamples)' function
178 | virtual SAMPLETYPE *ptrBegin()
179 | {
180 | return output->ptrBegin();
181 | }
182 |
183 | public:
184 |
185 | /// Output samples from beginning of the sample buffer. Copies requested samples to
186 | /// output buffer and removes them from the sample buffer. If there are less than
187 | /// 'numsample' samples in the buffer, returns all that available.
188 | ///
189 | /// \return Number of samples returned.
190 | virtual uint receiveSamples(SAMPLETYPE *outBuffer, ///< Buffer where to copy output samples.
191 | uint maxSamples ///< How many samples to receive at max.
192 | )
193 | {
194 | return output->receiveSamples(outBuffer, maxSamples);
195 | }
196 |
197 |
198 | /// Adjusts book-keeping so that given number of samples are removed from beginning of the
199 | /// sample buffer without copying them anywhere.
200 | ///
201 | /// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
202 | /// with 'ptrBegin' function.
203 | virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe.
204 | )
205 | {
206 | return output->receiveSamples(maxSamples);
207 | }
208 |
209 |
210 | /// Returns number of samples currently available.
211 | virtual uint numSamples() const
212 | {
213 | return output->numSamples();
214 | }
215 |
216 |
217 | /// Returns nonzero if there aren't any samples available for outputting.
218 | virtual int isEmpty() const
219 | {
220 | return output->isEmpty();
221 | }
222 |
223 | /// allow trimming (downwards) amount of samples in pipeline.
224 | /// Returns adjusted amount of samples
225 | virtual uint adjustAmountOfSamples(uint numSamples)
226 | {
227 | return output->adjustAmountOfSamples(numSamples);
228 | }
229 |
230 | };
231 |
232 | }
233 |
234 | #endif
235 |
--------------------------------------------------------------------------------
/SoundTouch/FIRFilter.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// General FIR digital filter routines with MMX optimization.
4 | ///
5 | /// Note : MMX optimized functions reside in a separate, platform-specific file,
6 | /// e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'
7 | ///
8 | /// Author : Copyright (c) Olli Parviainen
9 | /// Author e-mail : oparviai 'at' iki.fi
10 | /// SoundTouch WWW: http://www.surina.net/soundtouch
11 | ///
12 | ////////////////////////////////////////////////////////////////////////////////
13 | //
14 | // Last changed : $Date: 2015-02-21 23:24:29 +0200 (Sat, 21 Feb 2015) $
15 | // File revision : $Revision: 4 $
16 | //
17 | // $Id: FIRFilter.cpp 202 2015-02-21 21:24:29Z oparviai $
18 | //
19 | ////////////////////////////////////////////////////////////////////////////////
20 | //
21 | // License :
22 | //
23 | // SoundTouch audio processing library
24 | // Copyright (c) Olli Parviainen
25 | //
26 | // This library is free software; you can redistribute it and/or
27 | // modify it under the terms of the GNU Lesser General Public
28 | // License as published by the Free Software Foundation; either
29 | // version 2.1 of the License, or (at your option) any later version.
30 | //
31 | // This library is distributed in the hope that it will be useful,
32 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
33 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34 | // Lesser General Public License for more details.
35 | //
36 | // You should have received a copy of the GNU Lesser General Public
37 | // License along with this library; if not, write to the Free Software
38 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39 | //
40 | ////////////////////////////////////////////////////////////////////////////////
41 |
42 | #include
43 | #include
44 | #include
45 | #include
46 | #include "FIRFilter.h"
47 | #include "cpu_detect.h"
48 |
49 | using namespace soundtouch;
50 |
51 | /*****************************************************************************
52 | *
53 | * Implementation of the class 'FIRFilter'
54 | *
55 | *****************************************************************************/
56 |
57 | FIRFilter::FIRFilter()
58 | {
59 | resultDivFactor = 0;
60 | resultDivider = 0;
61 | length = 0;
62 | lengthDiv8 = 0;
63 | filterCoeffs = NULL;
64 | }
65 |
66 |
67 | FIRFilter::~FIRFilter()
68 | {
69 | delete[] filterCoeffs;
70 | }
71 |
72 | // Usual C-version of the filter routine for stereo sound
73 | uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const
74 | {
75 | int j, end;
76 | #ifdef SOUNDTOUCH_FLOAT_SAMPLES
77 | // when using floating point samples, use a scaler instead of a divider
78 | // because division is much slower operation than multiplying.
79 | double dScaler = 1.0 / (double)resultDivider;
80 | #endif
81 |
82 | assert(length != 0);
83 | assert(src != NULL);
84 | assert(dest != NULL);
85 | assert(filterCoeffs != NULL);
86 |
87 | end = 2 * (numSamples - length);
88 |
89 | #pragma omp parallel for
90 | for (j = 0; j < end; j += 2)
91 | {
92 | const SAMPLETYPE *ptr;
93 | LONG_SAMPLETYPE suml, sumr;
94 | uint i;
95 |
96 | suml = sumr = 0;
97 | ptr = src + j;
98 |
99 | for (i = 0; i < length; i += 4)
100 | {
101 | // loop is unrolled by factor of 4 here for efficiency
102 | suml += ptr[2 * i + 0] * filterCoeffs[i + 0] +
103 | ptr[2 * i + 2] * filterCoeffs[i + 1] +
104 | ptr[2 * i + 4] * filterCoeffs[i + 2] +
105 | ptr[2 * i + 6] * filterCoeffs[i + 3];
106 | sumr += ptr[2 * i + 1] * filterCoeffs[i + 0] +
107 | ptr[2 * i + 3] * filterCoeffs[i + 1] +
108 | ptr[2 * i + 5] * filterCoeffs[i + 2] +
109 | ptr[2 * i + 7] * filterCoeffs[i + 3];
110 | }
111 |
112 | #ifdef SOUNDTOUCH_INTEGER_SAMPLES
113 | suml >>= resultDivFactor;
114 | sumr >>= resultDivFactor;
115 | // saturate to 16 bit integer limits
116 | suml = (suml < -32768) ? -32768 : (suml > 32767) ? 32767 : suml;
117 | // saturate to 16 bit integer limits
118 | sumr = (sumr < -32768) ? -32768 : (sumr > 32767) ? 32767 : sumr;
119 | #else
120 | suml *= dScaler;
121 | sumr *= dScaler;
122 | #endif // SOUNDTOUCH_INTEGER_SAMPLES
123 | dest[j] = (SAMPLETYPE)suml;
124 | dest[j + 1] = (SAMPLETYPE)sumr;
125 | }
126 | return numSamples - length;
127 | }
128 |
129 |
130 |
131 |
132 | // Usual C-version of the filter routine for mono sound
133 | uint FIRFilter::evaluateFilterMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const
134 | {
135 | int j, end;
136 | #ifdef SOUNDTOUCH_FLOAT_SAMPLES
137 | // when using floating point samples, use a scaler instead of a divider
138 | // because division is much slower operation than multiplying.
139 | double dScaler = 1.0 / (double)resultDivider;
140 | #endif
141 |
142 | assert(length != 0);
143 |
144 | end = numSamples - length;
145 | #pragma omp parallel for
146 | for (j = 0; j < end; j ++)
147 | {
148 | const SAMPLETYPE *pSrc = src + j;
149 | LONG_SAMPLETYPE sum;
150 | uint i;
151 |
152 | sum = 0;
153 | for (i = 0; i < length; i += 4)
154 | {
155 | // loop is unrolled by factor of 4 here for efficiency
156 | sum += pSrc[i + 0] * filterCoeffs[i + 0] +
157 | pSrc[i + 1] * filterCoeffs[i + 1] +
158 | pSrc[i + 2] * filterCoeffs[i + 2] +
159 | pSrc[i + 3] * filterCoeffs[i + 3];
160 | }
161 | #ifdef SOUNDTOUCH_INTEGER_SAMPLES
162 | sum >>= resultDivFactor;
163 | // saturate to 16 bit integer limits
164 | sum = (sum < -32768) ? -32768 : (sum > 32767) ? 32767 : sum;
165 | #else
166 | sum *= dScaler;
167 | #endif // SOUNDTOUCH_INTEGER_SAMPLES
168 | dest[j] = (SAMPLETYPE)sum;
169 | }
170 | return end;
171 | }
172 |
173 |
174 | uint FIRFilter::evaluateFilterMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels)
175 | {
176 | int j, end;
177 |
178 | #ifdef SOUNDTOUCH_FLOAT_SAMPLES
179 | // when using floating point samples, use a scaler instead of a divider
180 | // because division is much slower operation than multiplying.
181 | double dScaler = 1.0 / (double)resultDivider;
182 | #endif
183 |
184 | assert(length != 0);
185 | assert(src != NULL);
186 | assert(dest != NULL);
187 | assert(filterCoeffs != NULL);
188 | assert(numChannels < 16);
189 |
190 | end = numChannels * (numSamples - length);
191 |
192 | #pragma omp parallel for
193 | for (j = 0; j < end; j += numChannels)
194 | {
195 | const SAMPLETYPE *ptr;
196 | LONG_SAMPLETYPE sums[16];
197 | uint c, i;
198 |
199 | for (c = 0; c < numChannels; c ++)
200 | {
201 | sums[c] = 0;
202 | }
203 |
204 | ptr = src + j;
205 |
206 | for (i = 0; i < length; i ++)
207 | {
208 | SAMPLETYPE coef=filterCoeffs[i];
209 | for (c = 0; c < numChannels; c ++)
210 | {
211 | sums[c] += ptr[0] * coef;
212 | ptr ++;
213 | }
214 | }
215 |
216 | for (c = 0; c < numChannels; c ++)
217 | {
218 | #ifdef SOUNDTOUCH_INTEGER_SAMPLES
219 | sums[c] >>= resultDivFactor;
220 | #else
221 | sums[c] *= dScaler;
222 | #endif // SOUNDTOUCH_INTEGER_SAMPLES
223 | dest[j+c] = (SAMPLETYPE)sums[c];
224 | }
225 | }
226 | return numSamples - length;
227 | }
228 |
229 |
230 | // Set filter coeffiecients and length.
231 | //
232 | // Throws an exception if filter length isn't divisible by 8
233 | void FIRFilter::setCoefficients(const SAMPLETYPE *coeffs, uint newLength, uint uResultDivFactor)
234 | {
235 | assert(newLength > 0);
236 | if (newLength % 8) ST_THROW_RT_ERROR("FIR filter length not divisible by 8");
237 |
238 | lengthDiv8 = newLength / 8;
239 | length = lengthDiv8 * 8;
240 | assert(length == newLength);
241 |
242 | resultDivFactor = uResultDivFactor;
243 | resultDivider = (SAMPLETYPE)::pow(2.0, (int)resultDivFactor);
244 |
245 | delete[] filterCoeffs;
246 | filterCoeffs = new SAMPLETYPE[length];
247 | memcpy(filterCoeffs, coeffs, length * sizeof(SAMPLETYPE));
248 | }
249 |
250 |
251 | uint FIRFilter::getLength() const
252 | {
253 | return length;
254 | }
255 |
256 |
257 |
258 | // Applies the filter to the given sequence of samples.
259 | //
260 | // Note : The amount of outputted samples is by value of 'filter_length'
261 | // smaller than the amount of input samples.
262 | uint FIRFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels)
263 | {
264 | assert(length > 0);
265 | assert(lengthDiv8 * 8 == length);
266 |
267 | if (numSamples < length) return 0;
268 |
269 | #ifndef USE_MULTICH_ALWAYS
270 | if (numChannels == 1)
271 | {
272 | return evaluateFilterMono(dest, src, numSamples);
273 | }
274 | else if (numChannels == 2)
275 | {
276 | return evaluateFilterStereo(dest, src, numSamples);
277 | }
278 | else
279 | #endif // USE_MULTICH_ALWAYS
280 | {
281 | assert(numChannels > 0);
282 | return evaluateFilterMulti(dest, src, numSamples, numChannels);
283 | }
284 | }
285 |
286 |
287 |
288 | // Operator 'new' is overloaded so that it automatically creates a suitable instance
289 | // depending on if we've a MMX-capable CPU available or not.
290 | void * FIRFilter::operator new(size_t s)
291 | {
292 | // Notice! don't use "new FIRFilter" directly, use "newInstance" to create a new instance instead!
293 | ST_THROW_RT_ERROR("Error in FIRFilter::new: Don't use 'new FIRFilter', use 'newInstance' member instead!");
294 | return newInstance();
295 | }
296 |
297 |
298 | FIRFilter * FIRFilter::newInstance()
299 | {
300 | uint uExtensions;
301 |
302 | uExtensions = detectCPUextensions();
303 |
304 | // Check if MMX/SSE instruction set extensions supported by CPU
305 |
306 | #ifdef SOUNDTOUCH_ALLOW_MMX
307 | // MMX routines available only with integer sample types
308 | if (uExtensions & SUPPORT_MMX)
309 | {
310 | return ::new FIRFilterMMX;
311 | }
312 | else
313 | #endif // SOUNDTOUCH_ALLOW_MMX
314 |
315 | #ifdef SOUNDTOUCH_ALLOW_SSE
316 | if (uExtensions & SUPPORT_SSE)
317 | {
318 | // SSE support
319 | return ::new FIRFilterSSE;
320 | }
321 | else
322 | #endif // SOUNDTOUCH_ALLOW_SSE
323 |
324 | {
325 | // ISA optimizations not supported, use plain C version
326 | return ::new FIRFilter;
327 | }
328 | }
329 |
--------------------------------------------------------------------------------
/SoundTouch/FIRFilter.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// General FIR digital filter routines with MMX optimization.
4 | ///
5 | /// Note : MMX optimized functions reside in a separate, platform-specific file,
6 | /// e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'
7 | ///
8 | /// Author : Copyright (c) Olli Parviainen
9 | /// Author e-mail : oparviai 'at' iki.fi
10 | /// SoundTouch WWW: http://www.surina.net/soundtouch
11 | ///
12 | ////////////////////////////////////////////////////////////////////////////////
13 | //
14 | // Last changed : $Date: 2015-02-21 23:24:29 +0200 (Sat, 21 Feb 2015) $
15 | // File revision : $Revision: 4 $
16 | //
17 | // $Id: FIRFilter.h 202 2015-02-21 21:24:29Z oparviai $
18 | //
19 | ////////////////////////////////////////////////////////////////////////////////
20 | //
21 | // License :
22 | //
23 | // SoundTouch audio processing library
24 | // Copyright (c) Olli Parviainen
25 | //
26 | // This library is free software; you can redistribute it and/or
27 | // modify it under the terms of the GNU Lesser General Public
28 | // License as published by the Free Software Foundation; either
29 | // version 2.1 of the License, or (at your option) any later version.
30 | //
31 | // This library is distributed in the hope that it will be useful,
32 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
33 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34 | // Lesser General Public License for more details.
35 | //
36 | // You should have received a copy of the GNU Lesser General Public
37 | // License along with this library; if not, write to the Free Software
38 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39 | //
40 | ////////////////////////////////////////////////////////////////////////////////
41 |
42 | #ifndef FIRFilter_H
43 | #define FIRFilter_H
44 |
45 | #include
46 | #include "STTypes.h"
47 |
48 | namespace soundtouch
49 | {
50 |
51 | class FIRFilter
52 | {
53 | protected:
54 | // Number of FIR filter taps
55 | uint length;
56 | // Number of FIR filter taps divided by 8
57 | uint lengthDiv8;
58 |
59 | // Result divider factor in 2^k format
60 | uint resultDivFactor;
61 |
62 | // Result divider value.
63 | SAMPLETYPE resultDivider;
64 |
65 | // Memory for filter coefficients
66 | SAMPLETYPE *filterCoeffs;
67 |
68 | virtual uint evaluateFilterStereo(SAMPLETYPE *dest,
69 | const SAMPLETYPE *src,
70 | uint numSamples) const;
71 | virtual uint evaluateFilterMono(SAMPLETYPE *dest,
72 | const SAMPLETYPE *src,
73 | uint numSamples) const;
74 | virtual uint evaluateFilterMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels);
75 |
76 | public:
77 | FIRFilter();
78 | virtual ~FIRFilter();
79 |
80 | /// Operator 'new' is overloaded so that it automatically creates a suitable instance
81 | /// depending on if we've a MMX-capable CPU available or not.
82 | static void * operator new(size_t s);
83 |
84 | static FIRFilter *newInstance();
85 |
86 | /// Applies the filter to the given sequence of samples.
87 | /// Note : The amount of outputted samples is by value of 'filter_length'
88 | /// smaller than the amount of input samples.
89 | ///
90 | /// \return Number of samples copied to 'dest'.
91 | uint evaluate(SAMPLETYPE *dest,
92 | const SAMPLETYPE *src,
93 | uint numSamples,
94 | uint numChannels);
95 |
96 | uint getLength() const;
97 |
98 | virtual void setCoefficients(const SAMPLETYPE *coeffs,
99 | uint newLength,
100 | uint uResultDivFactor);
101 | };
102 |
103 |
104 | // Optional subclasses that implement CPU-specific optimizations:
105 |
106 | #ifdef SOUNDTOUCH_ALLOW_MMX
107 |
108 | /// Class that implements MMX optimized functions exclusive for 16bit integer samples type.
109 | class FIRFilterMMX : public FIRFilter
110 | {
111 | protected:
112 | short *filterCoeffsUnalign;
113 | short *filterCoeffsAlign;
114 |
115 | virtual uint evaluateFilterStereo(short *dest, const short *src, uint numSamples) const;
116 | public:
117 | FIRFilterMMX();
118 | ~FIRFilterMMX();
119 |
120 | virtual void setCoefficients(const short *coeffs, uint newLength, uint uResultDivFactor);
121 | };
122 |
123 | #endif // SOUNDTOUCH_ALLOW_MMX
124 |
125 |
126 | #ifdef SOUNDTOUCH_ALLOW_SSE
127 | /// Class that implements SSE optimized functions exclusive for floating point samples type.
128 | class FIRFilterSSE : public FIRFilter
129 | {
130 | protected:
131 | float *filterCoeffsUnalign;
132 | float *filterCoeffsAlign;
133 |
134 | virtual uint evaluateFilterStereo(float *dest, const float *src, uint numSamples) const;
135 | public:
136 | FIRFilterSSE();
137 | ~FIRFilterSSE();
138 |
139 | virtual void setCoefficients(const float *coeffs, uint newLength, uint uResultDivFactor);
140 | };
141 |
142 | #endif // SOUNDTOUCH_ALLOW_SSE
143 |
144 | }
145 |
146 | #endif // FIRFilter_H
147 |
--------------------------------------------------------------------------------
/SoundTouch/InterpolateCubic.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Cubic interpolation routine.
4 | ///
5 | /// Author : Copyright (c) Olli Parviainen
6 | /// Author e-mail : oparviai 'at' iki.fi
7 | /// SoundTouch WWW: http://www.surina.net/soundtouch
8 | ///
9 | ////////////////////////////////////////////////////////////////////////////////
10 | //
11 | // $Id: InterpolateCubic.cpp 179 2014-01-06 18:41:42Z oparviai $
12 | //
13 | ////////////////////////////////////////////////////////////////////////////////
14 | //
15 | // License :
16 | //
17 | // SoundTouch audio processing library
18 | // Copyright (c) Olli Parviainen
19 | //
20 | // This library is free software; you can redistribute it and/or
21 | // modify it under the terms of the GNU Lesser General Public
22 | // License as published by the Free Software Foundation; either
23 | // version 2.1 of the License, or (at your option) any later version.
24 | //
25 | // This library is distributed in the hope that it will be useful,
26 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
27 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 | // Lesser General Public License for more details.
29 | //
30 | // You should have received a copy of the GNU Lesser General Public
31 | // License along with this library; if not, write to the Free Software
32 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 | //
34 | ////////////////////////////////////////////////////////////////////////////////
35 |
36 | #include
37 | #include
38 | #include "InterpolateCubic.h"
39 | #include "STTypes.h"
40 |
41 | using namespace soundtouch;
42 |
43 | // cubic interpolation coefficients
44 | static const float _coeffs[]=
45 | { -0.5f, 1.0f, -0.5f, 0.0f,
46 | 1.5f, -2.5f, 0.0f, 1.0f,
47 | -1.5f, 2.0f, 0.5f, 0.0f,
48 | 0.5f, -0.5f, 0.0f, 0.0f};
49 |
50 |
51 | InterpolateCubic::InterpolateCubic()
52 | {
53 | fract = 0;
54 | }
55 |
56 |
57 | void InterpolateCubic::resetRegisters()
58 | {
59 | fract = 0;
60 | }
61 |
62 |
63 | /// Transpose mono audio. Returns number of produced output samples, and
64 | /// updates "srcSamples" to amount of consumed source samples
65 | int InterpolateCubic::transposeMono(SAMPLETYPE *pdest,
66 | const SAMPLETYPE *psrc,
67 | int &srcSamples)
68 | {
69 | int i;
70 | int srcSampleEnd = srcSamples - 4;
71 | int srcCount = 0;
72 |
73 | i = 0;
74 | while (srcCount < srcSampleEnd)
75 | {
76 | float out;
77 | const float x3 = 1.0f;
78 | const float x2 = (float)fract; // x
79 | const float x1 = x2*x2; // x^2
80 | const float x0 = x1*x2; // x^3
81 | float y0, y1, y2, y3;
82 |
83 | assert(fract < 1.0);
84 |
85 | y0 = _coeffs[0] * x0 + _coeffs[1] * x1 + _coeffs[2] * x2 + _coeffs[3] * x3;
86 | y1 = _coeffs[4] * x0 + _coeffs[5] * x1 + _coeffs[6] * x2 + _coeffs[7] * x3;
87 | y2 = _coeffs[8] * x0 + _coeffs[9] * x1 + _coeffs[10] * x2 + _coeffs[11] * x3;
88 | y3 = _coeffs[12] * x0 + _coeffs[13] * x1 + _coeffs[14] * x2 + _coeffs[15] * x3;
89 |
90 | out = y0 * psrc[0] + y1 * psrc[1] + y2 * psrc[2] + y3 * psrc[3];
91 |
92 | pdest[i] = (SAMPLETYPE)out;
93 | i ++;
94 |
95 | // update position fraction
96 | fract += rate;
97 | // update whole positions
98 | int whole = (int)fract;
99 | fract -= whole;
100 | psrc += whole;
101 | srcCount += whole;
102 | }
103 | srcSamples = srcCount;
104 | return i;
105 | }
106 |
107 |
108 | /// Transpose stereo audio. Returns number of produced output samples, and
109 | /// updates "srcSamples" to amount of consumed source samples
110 | int InterpolateCubic::transposeStereo(SAMPLETYPE *pdest,
111 | const SAMPLETYPE *psrc,
112 | int &srcSamples)
113 | {
114 | int i;
115 | int srcSampleEnd = srcSamples - 4;
116 | int srcCount = 0;
117 |
118 | i = 0;
119 | while (srcCount < srcSampleEnd)
120 | {
121 | const float x3 = 1.0f;
122 | const float x2 = (float)fract; // x
123 | const float x1 = x2*x2; // x^2
124 | const float x0 = x1*x2; // x^3
125 | float y0, y1, y2, y3;
126 | float out0, out1;
127 |
128 | assert(fract < 1.0);
129 |
130 | y0 = _coeffs[0] * x0 + _coeffs[1] * x1 + _coeffs[2] * x2 + _coeffs[3] * x3;
131 | y1 = _coeffs[4] * x0 + _coeffs[5] * x1 + _coeffs[6] * x2 + _coeffs[7] * x3;
132 | y2 = _coeffs[8] * x0 + _coeffs[9] * x1 + _coeffs[10] * x2 + _coeffs[11] * x3;
133 | y3 = _coeffs[12] * x0 + _coeffs[13] * x1 + _coeffs[14] * x2 + _coeffs[15] * x3;
134 |
135 | out0 = y0 * psrc[0] + y1 * psrc[2] + y2 * psrc[4] + y3 * psrc[6];
136 | out1 = y0 * psrc[1] + y1 * psrc[3] + y2 * psrc[5] + y3 * psrc[7];
137 |
138 | pdest[2*i] = (SAMPLETYPE)out0;
139 | pdest[2*i+1] = (SAMPLETYPE)out1;
140 | i ++;
141 |
142 | // update position fraction
143 | fract += rate;
144 | // update whole positions
145 | int whole = (int)fract;
146 | fract -= whole;
147 | psrc += 2*whole;
148 | srcCount += whole;
149 | }
150 | srcSamples = srcCount;
151 | return i;
152 | }
153 |
154 |
155 | /// Transpose multi-channel audio. Returns number of produced output samples, and
156 | /// updates "srcSamples" to amount of consumed source samples
157 | int InterpolateCubic::transposeMulti(SAMPLETYPE *pdest,
158 | const SAMPLETYPE *psrc,
159 | int &srcSamples)
160 | {
161 | int i;
162 | int srcSampleEnd = srcSamples - 4;
163 | int srcCount = 0;
164 |
165 | i = 0;
166 | while (srcCount < srcSampleEnd)
167 | {
168 | const float x3 = 1.0f;
169 | const float x2 = (float)fract; // x
170 | const float x1 = x2*x2; // x^2
171 | const float x0 = x1*x2; // x^3
172 | float y0, y1, y2, y3;
173 |
174 | assert(fract < 1.0);
175 |
176 | y0 = _coeffs[0] * x0 + _coeffs[1] * x1 + _coeffs[2] * x2 + _coeffs[3] * x3;
177 | y1 = _coeffs[4] * x0 + _coeffs[5] * x1 + _coeffs[6] * x2 + _coeffs[7] * x3;
178 | y2 = _coeffs[8] * x0 + _coeffs[9] * x1 + _coeffs[10] * x2 + _coeffs[11] * x3;
179 | y3 = _coeffs[12] * x0 + _coeffs[13] * x1 + _coeffs[14] * x2 + _coeffs[15] * x3;
180 |
181 | for (int c = 0; c < numChannels; c ++)
182 | {
183 | float out;
184 | out = y0 * psrc[c] + y1 * psrc[c + numChannels] + y2 * psrc[c + 2 * numChannels] + y3 * psrc[c + 3 * numChannels];
185 | pdest[0] = (SAMPLETYPE)out;
186 | pdest ++;
187 | }
188 | i ++;
189 |
190 | // update position fraction
191 | fract += rate;
192 | // update whole positions
193 | int whole = (int)fract;
194 | fract -= whole;
195 | psrc += numChannels*whole;
196 | srcCount += whole;
197 | }
198 | srcSamples = srcCount;
199 | return i;
200 | }
201 |
--------------------------------------------------------------------------------
/SoundTouch/InterpolateCubic.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Cubic interpolation routine.
4 | ///
5 | /// Author : Copyright (c) Olli Parviainen
6 | /// Author e-mail : oparviai 'at' iki.fi
7 | /// SoundTouch WWW: http://www.surina.net/soundtouch
8 | ///
9 | ////////////////////////////////////////////////////////////////////////////////
10 | //
11 | // $Id: InterpolateCubic.h 225 2015-07-26 14:45:48Z oparviai $
12 | //
13 | ////////////////////////////////////////////////////////////////////////////////
14 | //
15 | // License :
16 | //
17 | // SoundTouch audio processing library
18 | // Copyright (c) Olli Parviainen
19 | //
20 | // This library is free software; you can redistribute it and/or
21 | // modify it under the terms of the GNU Lesser General Public
22 | // License as published by the Free Software Foundation; either
23 | // version 2.1 of the License, or (at your option) any later version.
24 | //
25 | // This library is distributed in the hope that it will be useful,
26 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
27 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 | // Lesser General Public License for more details.
29 | //
30 | // You should have received a copy of the GNU Lesser General Public
31 | // License along with this library; if not, write to the Free Software
32 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 | //
34 | ////////////////////////////////////////////////////////////////////////////////
35 |
36 | #ifndef _InterpolateCubic_H_
37 | #define _InterpolateCubic_H_
38 |
39 | #include "RateTransposer.h"
40 | #include "STTypes.h"
41 |
42 | namespace soundtouch
43 | {
44 |
45 | class InterpolateCubic : public TransposerBase
46 | {
47 | protected:
48 | virtual void resetRegisters();
49 | virtual int transposeMono(SAMPLETYPE *dest,
50 | const SAMPLETYPE *src,
51 | int &srcSamples);
52 | virtual int transposeStereo(SAMPLETYPE *dest,
53 | const SAMPLETYPE *src,
54 | int &srcSamples);
55 | virtual int transposeMulti(SAMPLETYPE *dest,
56 | const SAMPLETYPE *src,
57 | int &srcSamples);
58 |
59 | double fract;
60 |
61 | public:
62 | InterpolateCubic();
63 | };
64 |
65 | }
66 |
67 | #endif
68 |
--------------------------------------------------------------------------------
/SoundTouch/InterpolateLinear.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Linear interpolation algorithm.
4 | ///
5 | /// Author : Copyright (c) Olli Parviainen
6 | /// Author e-mail : oparviai 'at' iki.fi
7 | /// SoundTouch WWW: http://www.surina.net/soundtouch
8 | ///
9 | ////////////////////////////////////////////////////////////////////////////////
10 | //
11 | // $Id: InterpolateLinear.cpp 225 2015-07-26 14:45:48Z oparviai $
12 | //
13 | ////////////////////////////////////////////////////////////////////////////////
14 | //
15 | // License :
16 | //
17 | // SoundTouch audio processing library
18 | // Copyright (c) Olli Parviainen
19 | //
20 | // This library is free software; you can redistribute it and/or
21 | // modify it under the terms of the GNU Lesser General Public
22 | // License as published by the Free Software Foundation; either
23 | // version 2.1 of the License, or (at your option) any later version.
24 | //
25 | // This library is distributed in the hope that it will be useful,
26 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
27 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 | // Lesser General Public License for more details.
29 | //
30 | // You should have received a copy of the GNU Lesser General Public
31 | // License along with this library; if not, write to the Free Software
32 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 | //
34 | ////////////////////////////////////////////////////////////////////////////////
35 |
36 | #include
37 | #include
38 | #include "InterpolateLinear.h"
39 |
40 | using namespace soundtouch;
41 |
42 | //////////////////////////////////////////////////////////////////////////////
43 | //
44 | // InterpolateLinearInteger - integer arithmetic implementation
45 | //
46 |
47 | /// fixed-point interpolation routine precision
48 | #define SCALE 65536
49 |
50 |
51 | // Constructor
52 | InterpolateLinearInteger::InterpolateLinearInteger() : TransposerBase()
53 | {
54 | // Notice: use local function calling syntax for sake of clarity,
55 | // to indicate the fact that C++ constructor can't call virtual functions.
56 | resetRegisters();
57 | setRate(1.0f);
58 | }
59 |
60 |
61 | void InterpolateLinearInteger::resetRegisters()
62 | {
63 | iFract = 0;
64 | }
65 |
66 |
67 | // Transposes the sample rate of the given samples using linear interpolation.
68 | // 'Mono' version of the routine. Returns the number of samples returned in
69 | // the "dest" buffer
70 | int InterpolateLinearInteger::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
71 | {
72 | int i;
73 | int srcSampleEnd = srcSamples - 1;
74 | int srcCount = 0;
75 |
76 | i = 0;
77 | while (srcCount < srcSampleEnd)
78 | {
79 | LONG_SAMPLETYPE temp;
80 |
81 | assert(iFract < SCALE);
82 |
83 | temp = (SCALE - iFract) * src[0] + iFract * src[1];
84 | dest[i] = (SAMPLETYPE)(temp / SCALE);
85 | i++;
86 |
87 | iFract += iRate;
88 |
89 | int iWhole = iFract / SCALE;
90 | iFract -= iWhole * SCALE;
91 | srcCount += iWhole;
92 | src += iWhole;
93 | }
94 | srcSamples = srcCount;
95 |
96 | return i;
97 | }
98 |
99 |
100 | // Transposes the sample rate of the given samples using linear interpolation.
101 | // 'Stereo' version of the routine. Returns the number of samples returned in
102 | // the "dest" buffer
103 | int InterpolateLinearInteger::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
104 | {
105 | int i;
106 | int srcSampleEnd = srcSamples - 1;
107 | int srcCount = 0;
108 |
109 | i = 0;
110 | while (srcCount < srcSampleEnd)
111 | {
112 | LONG_SAMPLETYPE temp0;
113 | LONG_SAMPLETYPE temp1;
114 |
115 | assert(iFract < SCALE);
116 |
117 | temp0 = (SCALE - iFract) * src[0] + iFract * src[2];
118 | temp1 = (SCALE - iFract) * src[1] + iFract * src[3];
119 | dest[0] = (SAMPLETYPE)(temp0 / SCALE);
120 | dest[1] = (SAMPLETYPE)(temp1 / SCALE);
121 | dest += 2;
122 | i++;
123 |
124 | iFract += iRate;
125 |
126 | int iWhole = iFract / SCALE;
127 | iFract -= iWhole * SCALE;
128 | srcCount += iWhole;
129 | src += 2*iWhole;
130 | }
131 | srcSamples = srcCount;
132 |
133 | return i;
134 | }
135 |
136 |
137 | int InterpolateLinearInteger::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
138 | {
139 | int i;
140 | int srcSampleEnd = srcSamples - 1;
141 | int srcCount = 0;
142 |
143 | i = 0;
144 | while (srcCount < srcSampleEnd)
145 | {
146 | LONG_SAMPLETYPE temp, vol1;
147 |
148 | assert(iFract < SCALE);
149 | vol1 = (SCALE - iFract);
150 | for (int c = 0; c < numChannels; c ++)
151 | {
152 | temp = vol1 * src[c] + iFract * src[c + numChannels];
153 | dest[0] = (SAMPLETYPE)(temp / SCALE);
154 | dest ++;
155 | }
156 | i++;
157 |
158 | iFract += iRate;
159 |
160 | int iWhole = iFract / SCALE;
161 | iFract -= iWhole * SCALE;
162 | srcCount += iWhole;
163 | src += iWhole * numChannels;
164 | }
165 | srcSamples = srcCount;
166 |
167 | return i;
168 | }
169 |
170 |
171 | // Sets new target iRate. Normal iRate = 1.0, smaller values represent slower
172 | // iRate, larger faster iRates.
173 | void InterpolateLinearInteger::setRate(double newRate)
174 | {
175 | iRate = (int)(newRate * SCALE + 0.5);
176 | TransposerBase::setRate(newRate);
177 | }
178 |
179 |
180 | //////////////////////////////////////////////////////////////////////////////
181 | //
182 | // InterpolateLinearFloat - floating point arithmetic implementation
183 | //
184 | //////////////////////////////////////////////////////////////////////////////
185 |
186 |
187 | // Constructor
188 | InterpolateLinearFloat::InterpolateLinearFloat() : TransposerBase()
189 | {
190 | // Notice: use local function calling syntax for sake of clarity,
191 | // to indicate the fact that C++ constructor can't call virtual functions.
192 | resetRegisters();
193 | setRate(1.0);
194 | }
195 |
196 |
197 | void InterpolateLinearFloat::resetRegisters()
198 | {
199 | fract = 0;
200 | }
201 |
202 |
203 | // Transposes the sample rate of the given samples using linear interpolation.
204 | // 'Mono' version of the routine. Returns the number of samples returned in
205 | // the "dest" buffer
206 | int InterpolateLinearFloat::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
207 | {
208 | int i;
209 | int srcSampleEnd = srcSamples - 1;
210 | int srcCount = 0;
211 |
212 | i = 0;
213 | while (srcCount < srcSampleEnd)
214 | {
215 | double out;
216 | assert(fract < 1.0);
217 |
218 | out = (1.0 - fract) * src[0] + fract * src[1];
219 | dest[i] = (SAMPLETYPE)out;
220 | i ++;
221 |
222 | // update position fraction
223 | fract += rate;
224 | // update whole positions
225 | int whole = (int)fract;
226 | fract -= whole;
227 | src += whole;
228 | srcCount += whole;
229 | }
230 | srcSamples = srcCount;
231 | return i;
232 | }
233 |
234 |
235 | // Transposes the sample rate of the given samples using linear interpolation.
236 | // 'Mono' version of the routine. Returns the number of samples returned in
237 | // the "dest" buffer
238 | int InterpolateLinearFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
239 | {
240 | int i;
241 | int srcSampleEnd = srcSamples - 1;
242 | int srcCount = 0;
243 |
244 | i = 0;
245 | while (srcCount < srcSampleEnd)
246 | {
247 | double out0, out1;
248 | assert(fract < 1.0);
249 |
250 | out0 = (1.0 - fract) * src[0] + fract * src[2];
251 | out1 = (1.0 - fract) * src[1] + fract * src[3];
252 | dest[2*i] = (SAMPLETYPE)out0;
253 | dest[2*i+1] = (SAMPLETYPE)out1;
254 | i ++;
255 |
256 | // update position fraction
257 | fract += rate;
258 | // update whole positions
259 | int whole = (int)fract;
260 | fract -= whole;
261 | src += 2*whole;
262 | srcCount += whole;
263 | }
264 | srcSamples = srcCount;
265 | return i;
266 | }
267 |
268 |
269 | int InterpolateLinearFloat::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
270 | {
271 | int i;
272 | int srcSampleEnd = srcSamples - 1;
273 | int srcCount = 0;
274 |
275 | i = 0;
276 | while (srcCount < srcSampleEnd)
277 | {
278 | float temp, vol1, fract_float;
279 |
280 | vol1 = (float)(1.0 - fract);
281 | fract_float = (float)fract;
282 | for (int c = 0; c < numChannels; c ++)
283 | {
284 | temp = vol1 * src[c] + fract_float * src[c + numChannels];
285 | *dest = (SAMPLETYPE)temp;
286 | dest ++;
287 | }
288 | i++;
289 |
290 | fract += rate;
291 |
292 | int iWhole = (int)fract;
293 | fract -= iWhole;
294 | srcCount += iWhole;
295 | src += iWhole * numChannels;
296 | }
297 | srcSamples = srcCount;
298 |
299 | return i;
300 | }
301 |
--------------------------------------------------------------------------------
/SoundTouch/InterpolateLinear.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Linear interpolation routine.
4 | ///
5 | /// Author : Copyright (c) Olli Parviainen
6 | /// Author e-mail : oparviai 'at' iki.fi
7 | /// SoundTouch WWW: http://www.surina.net/soundtouch
8 | ///
9 | ////////////////////////////////////////////////////////////////////////////////
10 | //
11 | // $Id: InterpolateLinear.h 225 2015-07-26 14:45:48Z oparviai $
12 | //
13 | ////////////////////////////////////////////////////////////////////////////////
14 | //
15 | // License :
16 | //
17 | // SoundTouch audio processing library
18 | // Copyright (c) Olli Parviainen
19 | //
20 | // This library is free software; you can redistribute it and/or
21 | // modify it under the terms of the GNU Lesser General Public
22 | // License as published by the Free Software Foundation; either
23 | // version 2.1 of the License, or (at your option) any later version.
24 | //
25 | // This library is distributed in the hope that it will be useful,
26 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
27 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 | // Lesser General Public License for more details.
29 | //
30 | // You should have received a copy of the GNU Lesser General Public
31 | // License along with this library; if not, write to the Free Software
32 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 | //
34 | ////////////////////////////////////////////////////////////////////////////////
35 |
36 | #ifndef _InterpolateLinear_H_
37 | #define _InterpolateLinear_H_
38 |
39 | #include "RateTransposer.h"
40 | #include "STTypes.h"
41 |
42 | namespace soundtouch
43 | {
44 |
45 | /// Linear transposer class that uses integer arithmetics
46 | class InterpolateLinearInteger : public TransposerBase
47 | {
48 | protected:
49 | int iFract;
50 | int iRate;
51 |
52 | virtual void resetRegisters();
53 |
54 | virtual int transposeMono(SAMPLETYPE *dest,
55 | const SAMPLETYPE *src,
56 | int &srcSamples);
57 | virtual int transposeStereo(SAMPLETYPE *dest,
58 | const SAMPLETYPE *src,
59 | int &srcSamples);
60 | virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples);
61 | public:
62 | InterpolateLinearInteger();
63 |
64 | /// Sets new target rate. Normal rate = 1.0, smaller values represent slower
65 | /// rate, larger faster rates.
66 | virtual void setRate(double newRate);
67 | };
68 |
69 |
70 | /// Linear transposer class that uses floating point arithmetics
71 | class InterpolateLinearFloat : public TransposerBase
72 | {
73 | protected:
74 | double fract;
75 |
76 | virtual void resetRegisters();
77 |
78 | virtual int transposeMono(SAMPLETYPE *dest,
79 | const SAMPLETYPE *src,
80 | int &srcSamples);
81 | virtual int transposeStereo(SAMPLETYPE *dest,
82 | const SAMPLETYPE *src,
83 | int &srcSamples);
84 | virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples);
85 |
86 | public:
87 | InterpolateLinearFloat();
88 | };
89 |
90 | }
91 |
92 | #endif
93 |
--------------------------------------------------------------------------------
/SoundTouch/InterpolateShannon.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Sample interpolation routine using 8-tap band-limited Shannon interpolation
4 | /// with kaiser window.
5 | ///
6 | /// Notice. This algorithm is remarkably much heavier than linear or cubic
7 | /// interpolation, and not remarkably better than cubic algorithm. Thus mostly
8 | /// for experimental purposes
9 | ///
10 | /// Author : Copyright (c) Olli Parviainen
11 | /// Author e-mail : oparviai 'at' iki.fi
12 | /// SoundTouch WWW: http://www.surina.net/soundtouch
13 | ///
14 | ////////////////////////////////////////////////////////////////////////////////
15 | //
16 | // $Id: InterpolateShannon.cpp 195 2014-04-06 15:57:21Z oparviai $
17 | //
18 | ////////////////////////////////////////////////////////////////////////////////
19 | //
20 | // License :
21 | //
22 | // SoundTouch audio processing library
23 | // Copyright (c) Olli Parviainen
24 | //
25 | // This library is free software; you can redistribute it and/or
26 | // modify it under the terms of the GNU Lesser General Public
27 | // License as published by the Free Software Foundation; either
28 | // version 2.1 of the License, or (at your option) any later version.
29 | //
30 | // This library is distributed in the hope that it will be useful,
31 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
32 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 | // Lesser General Public License for more details.
34 | //
35 | // You should have received a copy of the GNU Lesser General Public
36 | // License along with this library; if not, write to the Free Software
37 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
38 | //
39 | ////////////////////////////////////////////////////////////////////////////////
40 |
41 | #include
42 | #include "InterpolateShannon.h"
43 | #include "STTypes.h"
44 |
45 | using namespace soundtouch;
46 |
47 |
48 | /// Kaiser window with beta = 2.0
49 | /// Values scaled down by 5% to avoid overflows
50 | static const double _kaiser8[8] =
51 | {
52 | 0.41778693317814,
53 | 0.64888025049173,
54 | 0.83508562409944,
55 | 0.93887857733412,
56 | 0.93887857733412,
57 | 0.83508562409944,
58 | 0.64888025049173,
59 | 0.41778693317814
60 | };
61 |
62 |
63 | InterpolateShannon::InterpolateShannon()
64 | {
65 | fract = 0;
66 | }
67 |
68 |
69 | void InterpolateShannon::resetRegisters()
70 | {
71 | fract = 0;
72 | }
73 |
74 |
75 | #define PI 3.1415926536
76 | #define sinc(x) (sin(PI * (x)) / (PI * (x)))
77 |
78 | /// Transpose mono audio. Returns number of produced output samples, and
79 | /// updates "srcSamples" to amount of consumed source samples
80 | int InterpolateShannon::transposeMono(SAMPLETYPE *pdest,
81 | const SAMPLETYPE *psrc,
82 | int &srcSamples)
83 | {
84 | int i;
85 | int srcSampleEnd = srcSamples - 8;
86 | int srcCount = 0;
87 |
88 | i = 0;
89 | while (srcCount < srcSampleEnd)
90 | {
91 | double out;
92 | assert(fract < 1.0);
93 |
94 | out = psrc[0] * sinc(-3.0 - fract) * _kaiser8[0];
95 | out += psrc[1] * sinc(-2.0 - fract) * _kaiser8[1];
96 | out += psrc[2] * sinc(-1.0 - fract) * _kaiser8[2];
97 | if (fract < 1e-6)
98 | {
99 | out += psrc[3] * _kaiser8[3]; // sinc(0) = 1
100 | }
101 | else
102 | {
103 | out += psrc[3] * sinc(- fract) * _kaiser8[3];
104 | }
105 | out += psrc[4] * sinc( 1.0 - fract) * _kaiser8[4];
106 | out += psrc[5] * sinc( 2.0 - fract) * _kaiser8[5];
107 | out += psrc[6] * sinc( 3.0 - fract) * _kaiser8[6];
108 | out += psrc[7] * sinc( 4.0 - fract) * _kaiser8[7];
109 |
110 | pdest[i] = (SAMPLETYPE)out;
111 | i ++;
112 |
113 | // update position fraction
114 | fract += rate;
115 | // update whole positions
116 | int whole = (int)fract;
117 | fract -= whole;
118 | psrc += whole;
119 | srcCount += whole;
120 | }
121 | srcSamples = srcCount;
122 | return i;
123 | }
124 |
125 |
126 | /// Transpose stereo audio. Returns number of produced output samples, and
127 | /// updates "srcSamples" to amount of consumed source samples
128 | int InterpolateShannon::transposeStereo(SAMPLETYPE *pdest,
129 | const SAMPLETYPE *psrc,
130 | int &srcSamples)
131 | {
132 | int i;
133 | int srcSampleEnd = srcSamples - 8;
134 | int srcCount = 0;
135 |
136 | i = 0;
137 | while (srcCount < srcSampleEnd)
138 | {
139 | double out0, out1, w;
140 | assert(fract < 1.0);
141 |
142 | w = sinc(-3.0 - fract) * _kaiser8[0];
143 | out0 = psrc[0] * w; out1 = psrc[1] * w;
144 | w = sinc(-2.0 - fract) * _kaiser8[1];
145 | out0 += psrc[2] * w; out1 += psrc[3] * w;
146 | w = sinc(-1.0 - fract) * _kaiser8[2];
147 | out0 += psrc[4] * w; out1 += psrc[5] * w;
148 | w = _kaiser8[3] * ((fract < 1e-5) ? 1.0 : sinc(- fract)); // sinc(0) = 1
149 | out0 += psrc[6] * w; out1 += psrc[7] * w;
150 | w = sinc( 1.0 - fract) * _kaiser8[4];
151 | out0 += psrc[8] * w; out1 += psrc[9] * w;
152 | w = sinc( 2.0 - fract) * _kaiser8[5];
153 | out0 += psrc[10] * w; out1 += psrc[11] * w;
154 | w = sinc( 3.0 - fract) * _kaiser8[6];
155 | out0 += psrc[12] * w; out1 += psrc[13] * w;
156 | w = sinc( 4.0 - fract) * _kaiser8[7];
157 | out0 += psrc[14] * w; out1 += psrc[15] * w;
158 |
159 | pdest[2*i] = (SAMPLETYPE)out0;
160 | pdest[2*i+1] = (SAMPLETYPE)out1;
161 | i ++;
162 |
163 | // update position fraction
164 | fract += rate;
165 | // update whole positions
166 | int whole = (int)fract;
167 | fract -= whole;
168 | psrc += 2*whole;
169 | srcCount += whole;
170 | }
171 | srcSamples = srcCount;
172 | return i;
173 | }
174 |
175 |
176 | /// Transpose stereo audio. Returns number of produced output samples, and
177 | /// updates "srcSamples" to amount of consumed source samples
178 | int InterpolateShannon::transposeMulti(SAMPLETYPE *pdest,
179 | const SAMPLETYPE *psrc,
180 | int &srcSamples)
181 | {
182 | // not implemented
183 | assert(false);
184 | return 0;
185 | }
186 |
--------------------------------------------------------------------------------
/SoundTouch/InterpolateShannon.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Sample interpolation routine using 8-tap band-limited Shannon interpolation
4 | /// with kaiser window.
5 | ///
6 | /// Notice. This algorithm is remarkably much heavier than linear or cubic
7 | /// interpolation, and not remarkably better than cubic algorithm. Thus mostly
8 | /// for experimental purposes
9 | ///
10 | /// Author : Copyright (c) Olli Parviainen
11 | /// Author e-mail : oparviai 'at' iki.fi
12 | /// SoundTouch WWW: http://www.surina.net/soundtouch
13 | ///
14 | ////////////////////////////////////////////////////////////////////////////////
15 | //
16 | // $Id: InterpolateShannon.h 225 2015-07-26 14:45:48Z oparviai $
17 | //
18 | ////////////////////////////////////////////////////////////////////////////////
19 | //
20 | // License :
21 | //
22 | // SoundTouch audio processing library
23 | // Copyright (c) Olli Parviainen
24 | //
25 | // This library is free software; you can redistribute it and/or
26 | // modify it under the terms of the GNU Lesser General Public
27 | // License as published by the Free Software Foundation; either
28 | // version 2.1 of the License, or (at your option) any later version.
29 | //
30 | // This library is distributed in the hope that it will be useful,
31 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
32 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 | // Lesser General Public License for more details.
34 | //
35 | // You should have received a copy of the GNU Lesser General Public
36 | // License along with this library; if not, write to the Free Software
37 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
38 | //
39 | ////////////////////////////////////////////////////////////////////////////////
40 |
41 | #ifndef _InterpolateShannon_H_
42 | #define _InterpolateShannon_H_
43 |
44 | #include "RateTransposer.h"
45 | #include "STTypes.h"
46 |
47 | namespace soundtouch
48 | {
49 |
50 | class InterpolateShannon : public TransposerBase
51 | {
52 | protected:
53 | void resetRegisters();
54 | int transposeMono(SAMPLETYPE *dest,
55 | const SAMPLETYPE *src,
56 | int &srcSamples);
57 | int transposeStereo(SAMPLETYPE *dest,
58 | const SAMPLETYPE *src,
59 | int &srcSamples);
60 | int transposeMulti(SAMPLETYPE *dest,
61 | const SAMPLETYPE *src,
62 | int &srcSamples);
63 |
64 | double fract;
65 |
66 | public:
67 | InterpolateShannon();
68 | };
69 |
70 | }
71 |
72 | #endif
73 |
--------------------------------------------------------------------------------
/SoundTouch/PeakFinder.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Peak detection routine.
4 | ///
5 | /// The routine detects highest value on an array of values and calculates the
6 | /// precise peak location as a mass-center of the 'hump' around the peak value.
7 | ///
8 | /// Author : Copyright (c) Olli Parviainen
9 | /// Author e-mail : oparviai 'at' iki.fi
10 | /// SoundTouch WWW: http://www.surina.net/soundtouch
11 | ///
12 | ////////////////////////////////////////////////////////////////////////////////
13 | //
14 | // Last changed : $Date: 2015-05-18 18:22:02 +0300 (Mon, 18 May 2015) $
15 | // File revision : $Revision: 4 $
16 | //
17 | // $Id: PeakFinder.cpp 213 2015-05-18 15:22:02Z oparviai $
18 | //
19 | ////////////////////////////////////////////////////////////////////////////////
20 | //
21 | // License :
22 | //
23 | // SoundTouch audio processing library
24 | // Copyright (c) Olli Parviainen
25 | //
26 | // This library is free software; you can redistribute it and/or
27 | // modify it under the terms of the GNU Lesser General Public
28 | // License as published by the Free Software Foundation; either
29 | // version 2.1 of the License, or (at your option) any later version.
30 | //
31 | // This library is distributed in the hope that it will be useful,
32 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
33 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34 | // Lesser General Public License for more details.
35 | //
36 | // You should have received a copy of the GNU Lesser General Public
37 | // License along with this library; if not, write to the Free Software
38 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39 | //
40 | ////////////////////////////////////////////////////////////////////////////////
41 |
42 | #include
43 | #include
44 |
45 | #include "PeakFinder.h"
46 |
47 | using namespace soundtouch;
48 |
49 | #define max(x, y) (((x) > (y)) ? (x) : (y))
50 |
51 |
52 | PeakFinder::PeakFinder()
53 | {
54 | minPos = maxPos = 0;
55 | }
56 |
57 |
58 | // Finds real 'top' of a peak hump from neighnourhood of the given 'peakpos'.
59 | int PeakFinder::findTop(const float *data, int peakpos) const
60 | {
61 | int i;
62 | int start, end;
63 | float refvalue;
64 |
65 | refvalue = data[peakpos];
66 |
67 | // seek within ?0 points
68 | start = peakpos - 10;
69 | if (start < minPos) start = minPos;
70 | end = peakpos + 10;
71 | if (end > maxPos) end = maxPos;
72 |
73 | for (i = start; i <= end; i ++)
74 | {
75 | if (data[i] > refvalue)
76 | {
77 | peakpos = i;
78 | refvalue = data[i];
79 | }
80 | }
81 |
82 | // failure if max value is at edges of seek range => it's not peak, it's at slope.
83 | if ((peakpos == start) || (peakpos == end)) return 0;
84 |
85 | return peakpos;
86 | }
87 |
88 |
89 | // Finds 'ground level' of a peak hump by starting from 'peakpos' and proceeding
90 | // to direction defined by 'direction' until next 'hump' after minimum value will
91 | // begin
92 | int PeakFinder::findGround(const float *data, int peakpos, int direction) const
93 | {
94 | int lowpos;
95 | int pos;
96 | int climb_count;
97 | float refvalue;
98 | float delta;
99 |
100 | climb_count = 0;
101 | refvalue = data[peakpos];
102 | lowpos = peakpos;
103 |
104 | pos = peakpos;
105 |
106 | while ((pos > minPos+1) && (pos < maxPos-1))
107 | {
108 | int prevpos;
109 |
110 | prevpos = pos;
111 | pos += direction;
112 |
113 | // calculate derivate
114 | delta = data[pos] - data[prevpos];
115 | if (delta <= 0)
116 | {
117 | // going downhill, ok
118 | if (climb_count)
119 | {
120 | climb_count --; // decrease climb count
121 | }
122 |
123 | // check if new minimum found
124 | if (data[pos] < refvalue)
125 | {
126 | // new minimum found
127 | lowpos = pos;
128 | refvalue = data[pos];
129 | }
130 | }
131 | else
132 | {
133 | // going uphill, increase climbing counter
134 | climb_count ++;
135 | if (climb_count > 5) break; // we've been climbing too long => it's next uphill => quit
136 | }
137 | }
138 | return lowpos;
139 | }
140 |
141 |
142 | // Find offset where the value crosses the given level, when starting from 'peakpos' and
143 | // proceeds to direction defined in 'direction'
144 | int PeakFinder::findCrossingLevel(const float *data, float level, int peakpos, int direction) const
145 | {
146 | float peaklevel;
147 | int pos;
148 |
149 | peaklevel = data[peakpos];
150 | assert(peaklevel >= level);
151 | pos = peakpos;
152 | while ((pos >= minPos) && (pos < maxPos))
153 | {
154 | if (data[pos + direction] < level) return pos; // crossing found
155 | pos += direction;
156 | }
157 | return -1; // not found
158 | }
159 |
160 |
161 | // Calculates the center of mass location of 'data' array items between 'firstPos' and 'lastPos'
162 | double PeakFinder::calcMassCenter(const float *data, int firstPos, int lastPos) const
163 | {
164 | int i;
165 | float sum;
166 | float wsum;
167 |
168 | sum = 0;
169 | wsum = 0;
170 | for (i = firstPos; i <= lastPos; i ++)
171 | {
172 | sum += (float)i * data[i];
173 | wsum += data[i];
174 | }
175 |
176 | if (wsum < 1e-6) return 0;
177 | return sum / wsum;
178 | }
179 |
180 |
181 |
182 | /// get exact center of peak near given position by calculating local mass of center
183 | double PeakFinder::getPeakCenter(const float *data, int peakpos) const
184 | {
185 | float peakLevel; // peak level
186 | int crosspos1, crosspos2; // position where the peak 'hump' crosses cutting level
187 | float cutLevel; // cutting value
188 | float groundLevel; // ground level of the peak
189 | int gp1, gp2; // bottom positions of the peak 'hump'
190 |
191 | // find ground positions.
192 | gp1 = findGround(data, peakpos, -1);
193 | gp2 = findGround(data, peakpos, 1);
194 |
195 | peakLevel = data[peakpos];
196 |
197 | if (gp1 == gp2)
198 | {
199 | // avoid rounding errors when all are equal
200 | assert(gp1 == peakpos);
201 | cutLevel = groundLevel = peakLevel;
202 | } else {
203 | // get average of the ground levels
204 | groundLevel = 0.5f * (data[gp1] + data[gp2]);
205 |
206 | // calculate 70%-level of the peak
207 | cutLevel = 0.70f * peakLevel + 0.30f * groundLevel;
208 | }
209 |
210 | // find mid-level crossings
211 | crosspos1 = findCrossingLevel(data, cutLevel, peakpos, -1);
212 | crosspos2 = findCrossingLevel(data, cutLevel, peakpos, 1);
213 |
214 | if ((crosspos1 < 0) || (crosspos2 < 0)) return 0; // no crossing, no peak..
215 |
216 | // calculate mass center of the peak surroundings
217 | return calcMassCenter(data, crosspos1, crosspos2);
218 | }
219 |
220 |
221 |
222 | double PeakFinder::detectPeak(const float *data, int aminPos, int amaxPos)
223 | {
224 |
225 | int i;
226 | int peakpos; // position of peak level
227 | double highPeak, peak;
228 |
229 | this->minPos = aminPos;
230 | this->maxPos = amaxPos;
231 |
232 | // find absolute peak
233 | peakpos = minPos;
234 | peak = data[minPos];
235 | for (i = minPos + 1; i < maxPos; i ++)
236 | {
237 | if (data[i] > peak)
238 | {
239 | peak = data[i];
240 | peakpos = i;
241 | }
242 | }
243 |
244 | // Calculate exact location of the highest peak mass center
245 | highPeak = getPeakCenter(data, peakpos);
246 | peak = highPeak;
247 |
248 | // Now check if the highest peak were in fact harmonic of the true base beat peak
249 | // - sometimes the highest peak can be Nth harmonic of the true base peak yet
250 | // just a slightly higher than the true base
251 |
252 | for (i = 3; i < 10; i ++)
253 | {
254 | double peaktmp, harmonic;
255 | int i1,i2;
256 |
257 | harmonic = (double)i * 0.5;
258 | peakpos = (int)(highPeak / harmonic + 0.5f);
259 | if (peakpos < minPos) break;
260 | peakpos = findTop(data, peakpos); // seek true local maximum index
261 | if (peakpos == 0) continue; // no local max here
262 |
263 | // calculate mass-center of possible harmonic peak
264 | peaktmp = getPeakCenter(data, peakpos);
265 |
266 | // accept harmonic peak if
267 | // (a) it is found
268 | // (b) is within ?% of the expected harmonic interval
269 | // (c) has at least half x-corr value of the max. peak
270 |
271 | double diff = harmonic * peaktmp / highPeak;
272 | if ((diff < 0.96) || (diff > 1.04)) continue; // peak too afar from expected
273 |
274 | // now compare to highest detected peak
275 | i1 = (int)(highPeak + 0.5);
276 | i2 = (int)(peaktmp + 0.5);
277 | if (data[i2] >= 0.4*data[i1])
278 | {
279 | // The harmonic is at least half as high primary peak,
280 | // thus use the harmonic peak instead
281 | peak = peaktmp;
282 | }
283 | }
284 |
285 | return peak;
286 | }
287 |
--------------------------------------------------------------------------------
/SoundTouch/PeakFinder.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// The routine detects highest value on an array of values and calculates the
4 | /// precise peak location as a mass-center of the 'hump' around the peak value.
5 | ///
6 | /// Author : Copyright (c) Olli Parviainen
7 | /// Author e-mail : oparviai 'at' iki.fi
8 | /// SoundTouch WWW: http://www.surina.net/soundtouch
9 | ///
10 | ////////////////////////////////////////////////////////////////////////////////
11 | //
12 | // Last changed : $Date: 2011-12-30 22:33:46 +0200 (Fri, 30 Dec 2011) $
13 | // File revision : $Revision: 4 $
14 | //
15 | // $Id: PeakFinder.h 132 2011-12-30 20:33:46Z oparviai $
16 | //
17 | ////////////////////////////////////////////////////////////////////////////////
18 | //
19 | // License :
20 | //
21 | // SoundTouch audio processing library
22 | // Copyright (c) Olli Parviainen
23 | //
24 | // This library is free software; you can redistribute it and/or
25 | // modify it under the terms of the GNU Lesser General Public
26 | // License as published by the Free Software Foundation; either
27 | // version 2.1 of the License, or (at your option) any later version.
28 | //
29 | // This library is distributed in the hope that it will be useful,
30 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
31 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
32 | // Lesser General Public License for more details.
33 | //
34 | // You should have received a copy of the GNU Lesser General Public
35 | // License along with this library; if not, write to the Free Software
36 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
37 | //
38 | ////////////////////////////////////////////////////////////////////////////////
39 |
40 | #ifndef _PeakFinder_H_
41 | #define _PeakFinder_H_
42 |
43 | namespace soundtouch
44 | {
45 |
46 | class PeakFinder
47 | {
48 | protected:
49 | /// Min, max allowed peak positions within the data vector
50 | int minPos, maxPos;
51 |
52 | /// Calculates the mass center between given vector items.
53 | double calcMassCenter(const float *data, ///< Data vector.
54 | int firstPos, ///< Index of first vector item beloging to the peak.
55 | int lastPos ///< Index of last vector item beloging to the peak.
56 | ) const;
57 |
58 | /// Finds the data vector index where the monotoniously decreasing signal crosses the
59 | /// given level.
60 | int findCrossingLevel(const float *data, ///< Data vector.
61 | float level, ///< Goal crossing level.
62 | int peakpos, ///< Peak position index within the data vector.
63 | int direction /// Direction where to proceed from the peak: 1 = right, -1 = left.
64 | ) const;
65 |
66 | // Finds real 'top' of a peak hump from neighnourhood of the given 'peakpos'.
67 | int findTop(const float *data, int peakpos) const;
68 |
69 |
70 | /// Finds the 'ground' level, i.e. smallest level between two neighbouring peaks, to right-
71 | /// or left-hand side of the given peak position.
72 | int findGround(const float *data, /// Data vector.
73 | int peakpos, /// Peak position index within the data vector.
74 | int direction /// Direction where to proceed from the peak: 1 = right, -1 = left.
75 | ) const;
76 |
77 | /// get exact center of peak near given position by calculating local mass of center
78 | double getPeakCenter(const float *data, int peakpos) const;
79 |
80 | public:
81 | /// Constructor.
82 | PeakFinder();
83 |
84 | /// Detect exact peak position of the data vector by finding the largest peak 'hump'
85 | /// and calculating the mass-center location of the peak hump.
86 | ///
87 | /// \return The location of the largest base harmonic peak hump.
88 | double detectPeak(const float *data, /// Data vector to be analyzed. The data vector has
89 | /// to be at least 'maxPos' items long.
90 | int minPos, ///< Min allowed peak location within the vector data.
91 | int maxPos ///< Max allowed peak location within the vector data.
92 | );
93 | };
94 |
95 | }
96 |
97 | #endif // _PeakFinder_H_
98 |
--------------------------------------------------------------------------------
/SoundTouch/RateTransposer.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Sample rate transposer. Changes sample rate by using linear interpolation
4 | /// together with anti-alias filtering (first order interpolation with anti-
5 | /// alias filtering should be quite adequate for this application)
6 | ///
7 | /// Author : Copyright (c) Olli Parviainen
8 | /// Author e-mail : oparviai 'at' iki.fi
9 | /// SoundTouch WWW: http://www.surina.net/soundtouch
10 | ///
11 | ////////////////////////////////////////////////////////////////////////////////
12 | //
13 | // Last changed : $Date: 2015-07-26 17:45:48 +0300 (Sun, 26 Jul 2015) $
14 | // File revision : $Revision: 4 $
15 | //
16 | // $Id: RateTransposer.cpp 225 2015-07-26 14:45:48Z oparviai $
17 | //
18 | ////////////////////////////////////////////////////////////////////////////////
19 | //
20 | // License :
21 | //
22 | // SoundTouch audio processing library
23 | // Copyright (c) Olli Parviainen
24 | //
25 | // This library is free software; you can redistribute it and/or
26 | // modify it under the terms of the GNU Lesser General Public
27 | // License as published by the Free Software Foundation; either
28 | // version 2.1 of the License, or (at your option) any later version.
29 | //
30 | // This library is distributed in the hope that it will be useful,
31 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
32 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 | // Lesser General Public License for more details.
34 | //
35 | // You should have received a copy of the GNU Lesser General Public
36 | // License along with this library; if not, write to the Free Software
37 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
38 | //
39 | ////////////////////////////////////////////////////////////////////////////////
40 |
41 | #include
42 | #include
43 | #include
44 | #include
45 | #include "RateTransposer.h"
46 | #include "InterpolateLinear.h"
47 | #include "InterpolateCubic.h"
48 | #include "InterpolateShannon.h"
49 | #include "AAFilter.h"
50 |
51 | using namespace soundtouch;
52 |
53 | // Define default interpolation algorithm here
54 | TransposerBase::ALGORITHM TransposerBase::algorithm = TransposerBase::CUBIC;
55 |
56 |
57 | // Constructor
58 | RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer)
59 | {
60 | bUseAAFilter = true;
61 |
62 | // Instantiates the anti-alias filter
63 | pAAFilter = new AAFilter(64);
64 | pTransposer = TransposerBase::newInstance();
65 | }
66 |
67 |
68 |
69 | RateTransposer::~RateTransposer()
70 | {
71 | delete pAAFilter;
72 | delete pTransposer;
73 | }
74 |
75 |
76 |
77 | /// Enables/disables the anti-alias filter. Zero to disable, nonzero to enable
78 | void RateTransposer::enableAAFilter(bool newMode)
79 | {
80 | bUseAAFilter = newMode;
81 | }
82 |
83 |
84 | /// Returns nonzero if anti-alias filter is enabled.
85 | bool RateTransposer::isAAFilterEnabled() const
86 | {
87 | return bUseAAFilter;
88 | }
89 |
90 |
91 | AAFilter *RateTransposer::getAAFilter()
92 | {
93 | return pAAFilter;
94 | }
95 |
96 |
97 |
98 | // Sets new target iRate. Normal iRate = 1.0, smaller values represent slower
99 | // iRate, larger faster iRates.
100 | void RateTransposer::setRate(double newRate)
101 | {
102 | double fCutoff;
103 |
104 | pTransposer->setRate(newRate);
105 |
106 | // design a new anti-alias filter
107 | if (newRate > 1.0)
108 | {
109 | fCutoff = 0.5 / newRate;
110 | }
111 | else
112 | {
113 | fCutoff = 0.5 * newRate;
114 | }
115 | pAAFilter->setCutoffFreq(fCutoff);
116 | }
117 |
118 |
119 | // Adds 'nSamples' pcs of samples from the 'samples' memory position into
120 | // the input of the object.
121 | void RateTransposer::putSamples(const SAMPLETYPE *samples, uint nSamples)
122 | {
123 | processSamples(samples, nSamples);
124 | }
125 |
126 |
127 | // Transposes sample rate by applying anti-alias filter to prevent folding.
128 | // Returns amount of samples returned in the "dest" buffer.
129 | // The maximum amount of samples that can be returned at a time is set by
130 | // the 'set_returnBuffer_size' function.
131 | void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples)
132 | {
133 | uint count;
134 |
135 | if (nSamples == 0) return;
136 |
137 | // Store samples to input buffer
138 | inputBuffer.putSamples(src, nSamples);
139 |
140 | // If anti-alias filter is turned off, simply transpose without applying
141 | // the filter
142 | if (bUseAAFilter == false)
143 | {
144 | count = pTransposer->transpose(outputBuffer, inputBuffer);
145 | return;
146 | }
147 |
148 | assert(pAAFilter);
149 |
150 | // Transpose with anti-alias filter
151 | if (pTransposer->rate < 1.0f)
152 | {
153 | // If the parameter 'Rate' value is smaller than 1, first transpose
154 | // the samples and then apply the anti-alias filter to remove aliasing.
155 |
156 | // Transpose the samples, store the result to end of "midBuffer"
157 | pTransposer->transpose(midBuffer, inputBuffer);
158 |
159 | // Apply the anti-alias filter for transposed samples in midBuffer
160 | pAAFilter->evaluate(outputBuffer, midBuffer);
161 | }
162 | else
163 | {
164 | // If the parameter 'Rate' value is larger than 1, first apply the
165 | // anti-alias filter to remove high frequencies (prevent them from folding
166 | // over the lover frequencies), then transpose.
167 |
168 | // Apply the anti-alias filter for samples in inputBuffer
169 | pAAFilter->evaluate(midBuffer, inputBuffer);
170 |
171 | // Transpose the AA-filtered samples in "midBuffer"
172 | pTransposer->transpose(outputBuffer, midBuffer);
173 | }
174 | }
175 |
176 |
177 | // Sets the number of channels, 1 = mono, 2 = stereo
178 | void RateTransposer::setChannels(int nChannels)
179 | {
180 | assert(nChannels > 0);
181 |
182 | if (pTransposer->numChannels == nChannels) return;
183 | pTransposer->setChannels(nChannels);
184 |
185 | inputBuffer.setChannels(nChannels);
186 | midBuffer.setChannels(nChannels);
187 | outputBuffer.setChannels(nChannels);
188 | }
189 |
190 |
191 | // Clears all the samples in the object
192 | void RateTransposer::clear()
193 | {
194 | outputBuffer.clear();
195 | midBuffer.clear();
196 | inputBuffer.clear();
197 | }
198 |
199 |
200 | // Returns nonzero if there aren't any samples available for outputting.
201 | int RateTransposer::isEmpty() const
202 | {
203 | int res;
204 |
205 | res = FIFOProcessor::isEmpty();
206 | if (res == 0) return 0;
207 | return inputBuffer.isEmpty();
208 | }
209 |
210 |
211 | //////////////////////////////////////////////////////////////////////////////
212 | //
213 | // TransposerBase - Base class for interpolation
214 | //
215 |
216 | // static function to set interpolation algorithm
217 | void TransposerBase::setAlgorithm(TransposerBase::ALGORITHM a)
218 | {
219 | TransposerBase::algorithm = a;
220 | }
221 |
222 |
223 | // Transposes the sample rate of the given samples using linear interpolation.
224 | // Returns the number of samples returned in the "dest" buffer
225 | int TransposerBase::transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src)
226 | {
227 | int numSrcSamples = src.numSamples();
228 | int sizeDemand = (int)((double)numSrcSamples / rate) + 8;
229 | int numOutput;
230 | SAMPLETYPE *psrc = src.ptrBegin();
231 | SAMPLETYPE *pdest = dest.ptrEnd(sizeDemand);
232 |
233 | #ifndef USE_MULTICH_ALWAYS
234 | if (numChannels == 1)
235 | {
236 | numOutput = transposeMono(pdest, psrc, numSrcSamples);
237 | }
238 | else if (numChannels == 2)
239 | {
240 | numOutput = transposeStereo(pdest, psrc, numSrcSamples);
241 | }
242 | else
243 | #endif // USE_MULTICH_ALWAYS
244 | {
245 | assert(numChannels > 0);
246 | numOutput = transposeMulti(pdest, psrc, numSrcSamples);
247 | }
248 | dest.putSamples(numOutput);
249 | src.receiveSamples(numSrcSamples);
250 | return numOutput;
251 | }
252 |
253 |
254 | TransposerBase::TransposerBase()
255 | {
256 | numChannels = 0;
257 | rate = 1.0f;
258 | }
259 |
260 |
261 | TransposerBase::~TransposerBase()
262 | {
263 | }
264 |
265 |
266 | void TransposerBase::setChannels(int channels)
267 | {
268 | numChannels = channels;
269 | resetRegisters();
270 | }
271 |
272 |
273 | void TransposerBase::setRate(double newRate)
274 | {
275 | rate = newRate;
276 | }
277 |
278 |
279 | // static factory function
280 | TransposerBase *TransposerBase::newInstance()
281 | {
282 | #ifdef SOUNDTOUCH_INTEGER_SAMPLES
283 | // Notice: For integer arithmetics support only linear algorithm (due to simplest calculus)
284 | return ::new InterpolateLinearInteger;
285 | #else
286 | switch (algorithm)
287 | {
288 | case LINEAR:
289 | return new InterpolateLinearFloat;
290 |
291 | case CUBIC:
292 | return new InterpolateCubic;
293 |
294 | case SHANNON:
295 | return new InterpolateShannon;
296 |
297 | default:
298 | assert(false);
299 | return NULL;
300 | }
301 | #endif
302 | }
303 |
--------------------------------------------------------------------------------
/SoundTouch/RateTransposer.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Sample rate transposer. Changes sample rate by using linear interpolation
4 | /// together with anti-alias filtering (first order interpolation with anti-
5 | /// alias filtering should be quite adequate for this application).
6 | ///
7 | /// Use either of the derived classes of 'RateTransposerInteger' or
8 | /// 'RateTransposerFloat' for corresponding integer/floating point tranposing
9 | /// algorithm implementation.
10 | ///
11 | /// Author : Copyright (c) Olli Parviainen
12 | /// Author e-mail : oparviai 'at' iki.fi
13 | /// SoundTouch WWW: http://www.surina.net/soundtouch
14 | ///
15 | ////////////////////////////////////////////////////////////////////////////////
16 | //
17 | // Last changed : $Date: 2015-07-26 17:45:48 +0300 (Sun, 26 Jul 2015) $
18 | // File revision : $Revision: 4 $
19 | //
20 | // $Id: RateTransposer.h 225 2015-07-26 14:45:48Z oparviai $
21 | //
22 | ////////////////////////////////////////////////////////////////////////////////
23 | //
24 | // License :
25 | //
26 | // SoundTouch audio processing library
27 | // Copyright (c) Olli Parviainen
28 | //
29 | // This library is free software; you can redistribute it and/or
30 | // modify it under the terms of the GNU Lesser General Public
31 | // License as published by the Free Software Foundation; either
32 | // version 2.1 of the License, or (at your option) any later version.
33 | //
34 | // This library is distributed in the hope that it will be useful,
35 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
36 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
37 | // Lesser General Public License for more details.
38 | //
39 | // You should have received a copy of the GNU Lesser General Public
40 | // License along with this library; if not, write to the Free Software
41 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
42 | //
43 | ////////////////////////////////////////////////////////////////////////////////
44 |
45 | #ifndef RateTransposer_H
46 | #define RateTransposer_H
47 |
48 | #include
49 | #include "AAFilter.h"
50 | #include "FIFOSamplePipe.h"
51 | #include "FIFOSampleBuffer.h"
52 |
53 | #include "STTypes.h"
54 |
55 | namespace soundtouch
56 | {
57 |
58 | /// Abstract base class for transposer implementations (linear, advanced vs integer, float etc)
59 | class TransposerBase
60 | {
61 | public:
62 | enum ALGORITHM {
63 | LINEAR = 0,
64 | CUBIC,
65 | SHANNON
66 | };
67 |
68 | protected:
69 | virtual void resetRegisters() = 0;
70 |
71 | virtual int transposeMono(SAMPLETYPE *dest,
72 | const SAMPLETYPE *src,
73 | int &srcSamples) = 0;
74 | virtual int transposeStereo(SAMPLETYPE *dest,
75 | const SAMPLETYPE *src,
76 | int &srcSamples) = 0;
77 | virtual int transposeMulti(SAMPLETYPE *dest,
78 | const SAMPLETYPE *src,
79 | int &srcSamples) = 0;
80 |
81 | static ALGORITHM algorithm;
82 |
83 | public:
84 | double rate;
85 | int numChannels;
86 |
87 | TransposerBase();
88 | virtual ~TransposerBase();
89 |
90 | virtual int transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src);
91 | virtual void setRate(double newRate);
92 | virtual void setChannels(int channels);
93 |
94 | // static factory function
95 | static TransposerBase *newInstance();
96 |
97 | // static function to set interpolation algorithm
98 | static void setAlgorithm(ALGORITHM a);
99 | };
100 |
101 |
102 | /// A common linear samplerate transposer class.
103 | ///
104 | class RateTransposer : public FIFOProcessor
105 | {
106 | protected:
107 | /// Anti-alias filter object
108 | AAFilter *pAAFilter;
109 | TransposerBase *pTransposer;
110 |
111 | /// Buffer for collecting samples to feed the anti-alias filter between
112 | /// two batches
113 | FIFOSampleBuffer inputBuffer;
114 |
115 | /// Buffer for keeping samples between transposing & anti-alias filter
116 | FIFOSampleBuffer midBuffer;
117 |
118 | /// Output sample buffer
119 | FIFOSampleBuffer outputBuffer;
120 |
121 | bool bUseAAFilter;
122 |
123 |
124 | /// Transposes sample rate by applying anti-alias filter to prevent folding.
125 | /// Returns amount of samples returned in the "dest" buffer.
126 | /// The maximum amount of samples that can be returned at a time is set by
127 | /// the 'set_returnBuffer_size' function.
128 | void processSamples(const SAMPLETYPE *src,
129 | uint numSamples);
130 |
131 | public:
132 | RateTransposer();
133 | virtual ~RateTransposer();
134 |
135 | /// Operator 'new' is overloaded so that it automatically creates a suitable instance
136 | /// depending on if we're to use integer or floating point arithmetics.
137 | // static void *operator new(size_t s);
138 |
139 | /// Use this function instead of "new" operator to create a new instance of this class.
140 | /// This function automatically chooses a correct implementation, depending on if
141 | /// integer ot floating point arithmetics are to be used.
142 | // static RateTransposer *newInstance();
143 |
144 | /// Returns the output buffer object
145 | FIFOSamplePipe *getOutput() { return &outputBuffer; };
146 |
147 | /// Returns the store buffer object
148 | // FIFOSamplePipe *getStore() { return &storeBuffer; };
149 |
150 | /// Return anti-alias filter object
151 | AAFilter *getAAFilter();
152 |
153 | /// Enables/disables the anti-alias filter. Zero to disable, nonzero to enable
154 | void enableAAFilter(bool newMode);
155 |
156 | /// Returns nonzero if anti-alias filter is enabled.
157 | bool isAAFilterEnabled() const;
158 |
159 | /// Sets new target rate. Normal rate = 1.0, smaller values represent slower
160 | /// rate, larger faster rates.
161 | virtual void setRate(double newRate);
162 |
163 | /// Sets the number of channels, 1 = mono, 2 = stereo
164 | void setChannels(int channels);
165 |
166 | /// Adds 'numSamples' pcs of samples from the 'samples' memory position into
167 | /// the input of the object.
168 | void putSamples(const SAMPLETYPE *samples, uint numSamples);
169 |
170 | /// Clears all the samples in the object
171 | void clear();
172 |
173 | /// Returns nonzero if there aren't any samples available for outputting.
174 | int isEmpty() const;
175 | };
176 |
177 | }
178 |
179 | #endif
180 |
--------------------------------------------------------------------------------
/SoundTouch/STTypes.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Common type definitions for SoundTouch audio processing library.
4 | ///
5 | /// Author : Copyright (c) Olli Parviainen
6 | /// Author e-mail : oparviai 'at' iki.fi
7 | /// SoundTouch WWW: http://www.surina.net/soundtouch
8 | ///
9 | ////////////////////////////////////////////////////////////////////////////////
10 | //
11 | // Last changed : $Date: 2015-05-18 18:25:07 +0300 (Mon, 18 May 2015) $
12 | // File revision : $Revision: 3 $
13 | //
14 | // $Id: STTypes.h 215 2015-05-18 15:25:07Z oparviai $
15 | //
16 | ////////////////////////////////////////////////////////////////////////////////
17 | //
18 | // License :
19 | //
20 | // SoundTouch audio processing library
21 | // Copyright (c) Olli Parviainen
22 | //
23 | // This library is free software; you can redistribute it and/or
24 | // modify it under the terms of the GNU Lesser General Public
25 | // License as published by the Free Software Foundation; either
26 | // version 2.1 of the License, or (at your option) any later version.
27 | //
28 | // This library is distributed in the hope that it will be useful,
29 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
30 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
31 | // Lesser General Public License for more details.
32 | //
33 | // You should have received a copy of the GNU Lesser General Public
34 | // License along with this library; if not, write to the Free Software
35 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
36 | //
37 | ////////////////////////////////////////////////////////////////////////////////
38 |
39 | #ifndef STTypes_H
40 | #define STTypes_H
41 |
42 | typedef unsigned int uint;
43 | typedef unsigned long ulong;
44 |
45 | // Patch for MinGW: on Win64 long is 32-bit
46 | #ifdef _WIN64
47 | typedef unsigned long long ulongptr;
48 | #else
49 | typedef ulong ulongptr;
50 | #endif
51 |
52 |
53 | // Helper macro for aligning pointer up to next 16-byte boundary
54 | #define SOUNDTOUCH_ALIGN_POINTER_16(x) ( ( (ulongptr)(x) + 15 ) & ~(ulongptr)15 )
55 |
56 |
57 | #if (defined(__GNUC__) && !defined(ANDROID))
58 | // In GCC, include soundtouch_config.h made by config scritps.
59 | // Skip this in Android compilation that uses GCC but without configure scripts.
60 | #include "soundtouch_config.h"
61 | #endif
62 |
63 |
64 | namespace soundtouch
65 | {
66 | /// Activate these undef's to overrule the possible sampletype
67 | /// setting inherited from some other header file:
68 | //#undef SOUNDTOUCH_INTEGER_SAMPLES
69 | //#undef SOUNDTOUCH_FLOAT_SAMPLES
70 |
71 | /// If following flag is defined, always uses multichannel processing
72 | /// routines also for mono and stero sound. This is for routine testing
73 | /// purposes; output should be same with either routines, yet disabling
74 | /// the dedicated mono/stereo processing routines will result in slower
75 | /// runtime performance so recommendation is to keep this off.
76 | // #define USE_MULTICH_ALWAYS
77 |
78 | #if (defined(__SOFTFP__) && defined(ANDROID))
79 | // For Android compilation: Force use of Integer samples in case that
80 | // compilation uses soft-floating point emulation - soft-fp is way too slow
81 | #undef SOUNDTOUCH_FLOAT_SAMPLES
82 | #define SOUNDTOUCH_INTEGER_SAMPLES 1
83 | #endif
84 |
85 | #if !(SOUNDTOUCH_INTEGER_SAMPLES || SOUNDTOUCH_FLOAT_SAMPLES)
86 |
87 | /// Choose either 32bit floating point or 16bit integer sampletype
88 | /// by choosing one of the following defines, unless this selection
89 | /// has already been done in some other file.
90 | ////
91 | /// Notes:
92 | /// - In Windows environment, choose the sample format with the
93 | /// following defines.
94 | /// - In GNU environment, the floating point samples are used by
95 | /// default, but integer samples can be chosen by giving the
96 | /// following switch to the configure script:
97 | /// ./configure --enable-integer-samples
98 | /// However, if you still prefer to select the sample format here
99 | /// also in GNU environment, then please #undef the INTEGER_SAMPLE
100 | /// and FLOAT_SAMPLE defines first as in comments above.
101 | #define SOUNDTOUCH_INTEGER_SAMPLES 1 //< 16bit integer samples
102 | //#define SOUNDTOUCH_FLOAT_SAMPLES 1 //< 32bit float samples
103 |
104 | #endif
105 |
106 | #if (_M_IX86 || __i386__ || __x86_64__ || _M_X64)
107 | /// Define this to allow X86-specific assembler/intrinsic optimizations.
108 | /// Notice that library contains also usual C++ versions of each of these
109 | /// these routines, so if you're having difficulties getting the optimized
110 | /// routines compiled for whatever reason, you may disable these optimizations
111 | /// to make the library compile.
112 |
113 | #define SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS 1
114 |
115 | /// In GNU environment, allow the user to override this setting by
116 | /// giving the following switch to the configure script:
117 | /// ./configure --disable-x86-optimizations
118 | /// ./configure --enable-x86-optimizations=no
119 | #ifdef SOUNDTOUCH_DISABLE_X86_OPTIMIZATIONS
120 | #undef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS
121 | #endif
122 | #else
123 | /// Always disable optimizations when not using a x86 systems.
124 | #undef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS
125 |
126 | #endif
127 |
128 | // If defined, allows the SIMD-optimized routines to take minor shortcuts
129 | // for improved performance. Undefine to require faithfully similar SIMD
130 | // calculations as in normal C implementation.
131 | #define SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION 1
132 |
133 |
134 | #ifdef SOUNDTOUCH_INTEGER_SAMPLES
135 | // 16bit integer sample type
136 | typedef short SAMPLETYPE;
137 | // data type for sample accumulation: Use 32bit integer to prevent overflows
138 | typedef long LONG_SAMPLETYPE;
139 |
140 | #ifdef SOUNDTOUCH_FLOAT_SAMPLES
141 | // check that only one sample type is defined
142 | #error "conflicting sample types defined"
143 | #endif // SOUNDTOUCH_FLOAT_SAMPLES
144 |
145 | #ifdef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS
146 | // Allow MMX optimizations
147 | #define SOUNDTOUCH_ALLOW_MMX 1
148 | #endif
149 |
150 | #else
151 |
152 | // floating point samples
153 | typedef float SAMPLETYPE;
154 | // data type for sample accumulation: Use double to utilize full precision.
155 | typedef double LONG_SAMPLETYPE;
156 |
157 | #ifdef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS
158 | // Allow SSE optimizations
159 | #define SOUNDTOUCH_ALLOW_SSE 1
160 | #endif
161 |
162 | #endif // SOUNDTOUCH_INTEGER_SAMPLES
163 |
164 | };
165 |
166 | // define ST_NO_EXCEPTION_HANDLING switch to disable throwing std exceptions:
167 | // #define ST_NO_EXCEPTION_HANDLING 1
168 | #ifdef ST_NO_EXCEPTION_HANDLING
169 | // Exceptions disabled. Throw asserts instead if enabled.
170 | #include
171 | #define ST_THROW_RT_ERROR(x) {assert((const char *)x);}
172 | #else
173 | // use c++ standard exceptions
174 | #include
175 | #include
176 | #define ST_THROW_RT_ERROR(x) {throw std::runtime_error(x);}
177 | #endif
178 |
179 | // When this #define is active, eliminates a clicking sound when the "rate" or "pitch"
180 | // parameter setting crosses from value <1 to >=1 or vice versa during processing.
181 | // Default is off as such crossover is untypical case and involves a slight sound
182 | // quality compromise.
183 | //#define SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER 1
184 |
185 | #endif
186 |
--------------------------------------------------------------------------------
/SoundTouch/SoundTouch.h:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// SoundTouch - main class for tempo/pitch/rate adjusting routines.
4 | ///
5 | /// Notes:
6 | /// - Initialize the SoundTouch object instance by setting up the sound stream
7 | /// parameters with functions 'setSampleRate' and 'setChannels', then set
8 | /// desired tempo/pitch/rate settings with the corresponding functions.
9 | ///
10 | /// - The SoundTouch class behaves like a first-in-first-out pipeline: The
11 | /// samples that are to be processed are fed into one of the pipe by calling
12 | /// function 'putSamples', while the ready processed samples can be read
13 | /// from the other end of the pipeline with function 'receiveSamples'.
14 | ///
15 | /// - The SoundTouch processing classes require certain sized 'batches' of
16 | /// samples in order to process the sound. For this reason the classes buffer
17 | /// incoming samples until there are enough of samples available for
18 | /// processing, then they carry out the processing step and consequently
19 | /// make the processed samples available for outputting.
20 | ///
21 | /// - For the above reason, the processing routines introduce a certain
22 | /// 'latency' between the input and output, so that the samples input to
23 | /// SoundTouch may not be immediately available in the output, and neither
24 | /// the amount of outputtable samples may not immediately be in direct
25 | /// relationship with the amount of previously input samples.
26 | ///
27 | /// - The tempo/pitch/rate control parameters can be altered during processing.
28 | /// Please notice though that they aren't currently protected by semaphores,
29 | /// so in multi-thread application external semaphore protection may be
30 | /// required.
31 | ///
32 | /// - This class utilizes classes 'TDStretch' for tempo change (without modifying
33 | /// pitch) and 'RateTransposer' for changing the playback rate (that is, both
34 | /// tempo and pitch in the same ratio) of the sound. The third available control
35 | /// 'pitch' (change pitch but maintain tempo) is produced by a combination of
36 | /// combining the two other controls.
37 | ///
38 | /// Author : Copyright (c) Olli Parviainen
39 | /// Author e-mail : oparviai 'at' iki.fi
40 | /// SoundTouch WWW: http://www.surina.net/soundtouch
41 | ///
42 | ////////////////////////////////////////////////////////////////////////////////
43 | //
44 | // Last changed : $Date: 2015-09-20 10:38:32 +0300 (Sun, 20 Sep 2015) $
45 | // File revision : $Revision: 4 $
46 | //
47 | // $Id: SoundTouch.h 230 2015-09-20 07:38:32Z oparviai $
48 | //
49 | ////////////////////////////////////////////////////////////////////////////////
50 | //
51 | // License :
52 | //
53 | // SoundTouch audio processing library
54 | // Copyright (c) Olli Parviainen
55 | //
56 | // This library is free software; you can redistribute it and/or
57 | // modify it under the terms of the GNU Lesser General Public
58 | // License as published by the Free Software Foundation; either
59 | // version 2.1 of the License, or (at your option) any later version.
60 | //
61 | // This library is distributed in the hope that it will be useful,
62 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
63 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
64 | // Lesser General Public License for more details.
65 | //
66 | // You should have received a copy of the GNU Lesser General Public
67 | // License along with this library; if not, write to the Free Software
68 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
69 | //
70 | ////////////////////////////////////////////////////////////////////////////////
71 |
72 | #ifndef SoundTouch_H
73 | #define SoundTouch_H
74 |
75 | #include "FIFOSamplePipe.h"
76 | #include "STTypes.h"
77 |
78 | namespace soundtouch
79 | {
80 |
81 | /// Soundtouch library version string
82 | #define SOUNDTOUCH_VERSION "1.9.2"
83 |
84 | /// SoundTouch library version id
85 | #define SOUNDTOUCH_VERSION_ID (10902)
86 |
87 | //
88 | // Available setting IDs for the 'setSetting' & 'get_setting' functions:
89 |
90 | /// Enable/disable anti-alias filter in pitch transposer (0 = disable)
91 | #define SETTING_USE_AA_FILTER 0
92 |
93 | /// Pitch transposer anti-alias filter length (8 .. 128 taps, default = 32)
94 | #define SETTING_AA_FILTER_LENGTH 1
95 |
96 | /// Enable/disable quick seeking algorithm in tempo changer routine
97 | /// (enabling quick seeking lowers CPU utilization but causes a minor sound
98 | /// quality compromising)
99 | #define SETTING_USE_QUICKSEEK 2
100 |
101 | /// Time-stretch algorithm single processing sequence length in milliseconds. This determines
102 | /// to how long sequences the original sound is chopped in the time-stretch algorithm.
103 | /// See "STTypes.h" or README for more information.
104 | #define SETTING_SEQUENCE_MS 3
105 |
106 | /// Time-stretch algorithm seeking window length in milliseconds for algorithm that finds the
107 | /// best possible overlapping location. This determines from how wide window the algorithm
108 | /// may look for an optimal joining location when mixing the sound sequences back together.
109 | /// See "STTypes.h" or README for more information.
110 | #define SETTING_SEEKWINDOW_MS 4
111 |
112 | /// Time-stretch algorithm overlap length in milliseconds. When the chopped sound sequences
113 | /// are mixed back together, to form a continuous sound stream, this parameter defines over
114 | /// how long period the two consecutive sequences are let to overlap each other.
115 | /// See "STTypes.h" or README for more information.
116 | #define SETTING_OVERLAP_MS 5
117 |
118 |
119 | /// Call "getSetting" with this ID to query nominal average processing sequence
120 | /// size in samples. This value tells approcimate value how many input samples
121 | /// SoundTouch needs to gather before it does DSP processing run for the sample batch.
122 | ///
123 | /// Notices:
124 | /// - This is read-only parameter, i.e. setSetting ignores this parameter
125 | /// - Returned value is approximate average value, exact processing batch
126 | /// size may wary from time to time
127 | /// - This parameter value is not constant but may change depending on
128 | /// tempo/pitch/rate/samplerate settings.
129 | #define SETTING_NOMINAL_INPUT_SEQUENCE 6
130 |
131 |
132 | /// Call "getSetting" with this ID to query nominal average processing output
133 | /// size in samples. This value tells approcimate value how many output samples
134 | /// SoundTouch outputs once it does DSP processing run for a batch of input samples.
135 | ///
136 | /// Notices:
137 | /// - This is read-only parameter, i.e. setSetting ignores this parameter
138 | /// - Returned value is approximate average value, exact processing batch
139 | /// size may wary from time to time
140 | /// - This parameter value is not constant but may change depending on
141 | /// tempo/pitch/rate/samplerate settings.
142 | #define SETTING_NOMINAL_OUTPUT_SEQUENCE 7
143 |
144 | class SoundTouch : public FIFOProcessor
145 | {
146 | private:
147 | /// Rate transposer class instance
148 | class RateTransposer *pRateTransposer;
149 |
150 | /// Time-stretch class instance
151 | class TDStretch *pTDStretch;
152 |
153 | /// Virtual pitch parameter. Effective rate & tempo are calculated from these parameters.
154 | double virtualRate;
155 |
156 | /// Virtual pitch parameter. Effective rate & tempo are calculated from these parameters.
157 | double virtualTempo;
158 |
159 | /// Virtual pitch parameter. Effective rate & tempo are calculated from these parameters.
160 | double virtualPitch;
161 |
162 | /// Flag: Has sample rate been set?
163 | bool bSrateSet;
164 |
165 | /// Accumulator for how many samples in total will be expected as output vs. samples put in,
166 | /// considering current processing settings.
167 | double samplesExpectedOut;
168 |
169 | /// Accumulator for how many samples in total have been read out from the processing so far
170 | long samplesOutput;
171 |
172 | /// Calculates effective rate & tempo valuescfrom 'virtualRate', 'virtualTempo' and
173 | /// 'virtualPitch' parameters.
174 | void calcEffectiveRateAndTempo();
175 |
176 | protected :
177 | /// Number of channels
178 | uint channels;
179 |
180 | /// Effective 'rate' value calculated from 'virtualRate', 'virtualTempo' and 'virtualPitch'
181 | double rate;
182 |
183 | /// Effective 'tempo' value calculated from 'virtualRate', 'virtualTempo' and 'virtualPitch'
184 | double tempo;
185 |
186 | public:
187 | SoundTouch();
188 | virtual ~SoundTouch();
189 |
190 | /// Get SoundTouch library version string
191 | static const char *getVersionString();
192 |
193 | /// Get SoundTouch library version Id
194 | static uint getVersionId();
195 |
196 | /// Sets new rate control value. Normal rate = 1.0, smaller values
197 | /// represent slower rate, larger faster rates.
198 | void setRate(double newRate);
199 |
200 | /// Sets new tempo control value. Normal tempo = 1.0, smaller values
201 | /// represent slower tempo, larger faster tempo.
202 | void setTempo(double newTempo);
203 |
204 | /// Sets new rate control value as a difference in percents compared
205 | /// to the original rate (-50 .. +100 %)
206 | void setRateChange(double newRate);
207 |
208 | /// Sets new tempo control value as a difference in percents compared
209 | /// to the original tempo (-50 .. +100 %)
210 | void setTempoChange(double newTempo);
211 |
212 | /// Sets new pitch control value. Original pitch = 1.0, smaller values
213 | /// represent lower pitches, larger values higher pitch.
214 | void setPitch(double newPitch);
215 |
216 | /// Sets pitch change in octaves compared to the original pitch
217 | /// (-1.00 .. +1.00)
218 | void setPitchOctaves(double newPitch);
219 |
220 | /// Sets pitch change in semi-tones compared to the original pitch
221 | /// (-12 .. +12)
222 | void setPitchSemiTones(int newPitch);
223 | void setPitchSemiTones(double newPitch);
224 |
225 | /// Sets the number of channels, 1 = mono, 2 = stereo
226 | void setChannels(uint numChannels);
227 |
228 | /// Sets sample rate.
229 | void setSampleRate(uint srate);
230 |
231 | /// Flushes the last samples from the processing pipeline to the output.
232 | /// Clears also the internal processing buffers.
233 | //
234 | /// Note: This function is meant for extracting the last samples of a sound
235 | /// stream. This function may introduce additional blank samples in the end
236 | /// of the sound stream, and thus it's not recommended to call this function
237 | /// in the middle of a sound stream.
238 | void flush();
239 |
240 | /// Adds 'numSamples' pcs of samples from the 'samples' memory position into
241 | /// the input of the object. Notice that sample rate _has_to_ be set before
242 | /// calling this function, otherwise throws a runtime_error exception.
243 | virtual void putSamples(
244 | const SAMPLETYPE *samples, ///< Pointer to sample buffer.
245 | uint numSamples ///< Number of samples in buffer. Notice
246 | ///< that in case of stereo-sound a single sample
247 | ///< contains data for both channels.
248 | );
249 |
250 | /// Output samples from beginning of the sample buffer. Copies requested samples to
251 | /// output buffer and removes them from the sample buffer. If there are less than
252 | /// 'numsample' samples in the buffer, returns all that available.
253 | ///
254 | /// \return Number of samples returned.
255 | virtual uint receiveSamples(SAMPLETYPE *output, ///< Buffer where to copy output samples.
256 | uint maxSamples ///< How many samples to receive at max.
257 | );
258 |
259 | /// Adjusts book-keeping so that given number of samples are removed from beginning of the
260 | /// sample buffer without copying them anywhere.
261 | ///
262 | /// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
263 | /// with 'ptrBegin' function.
264 | virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe.
265 | );
266 |
267 | /// Clears all the samples in the object's output and internal processing
268 | /// buffers.
269 | virtual void clear();
270 |
271 | /// Changes a setting controlling the processing system behaviour. See the
272 | /// 'SETTING_...' defines for available setting ID's.
273 | ///
274 | /// \return 'true' if the setting was succesfully changed
275 | bool setSetting(int settingId, ///< Setting ID number. see SETTING_... defines.
276 | int value ///< New setting value.
277 | );
278 |
279 | /// Reads a setting controlling the processing system behaviour. See the
280 | /// 'SETTING_...' defines for available setting ID's.
281 | ///
282 | /// \return the setting value.
283 | int getSetting(int settingId ///< Setting ID number, see SETTING_... defines.
284 | ) const;
285 |
286 | /// Returns number of samples currently unprocessed.
287 | virtual uint numUnprocessedSamples() const;
288 |
289 |
290 | /// Other handy functions that are implemented in the ancestor classes (see
291 | /// classes 'FIFOProcessor' and 'FIFOSamplePipe')
292 | ///
293 | /// - receiveSamples() : Use this function to receive 'ready' processed samples from SoundTouch.
294 | /// - numSamples() : Get number of 'ready' samples that can be received with
295 | /// function 'receiveSamples()'
296 | /// - isEmpty() : Returns nonzero if there aren't any 'ready' samples.
297 | /// - clear() : Clears all samples from ready/processing buffers.
298 | };
299 |
300 | }
301 | #endif
302 |
--------------------------------------------------------------------------------
/SoundTouch/SoundTouch.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
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 | {32C0FBB2-32C4-452C-9971-8C21791CDB63}
47 | Win32Proj
48 | SoundTouch
49 |
50 |
51 |
52 | StaticLibrary
53 | true
54 | v120
55 | Unicode
56 |
57 |
58 | StaticLibrary
59 | false
60 | v120
61 | true
62 | Unicode
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | Level3
80 | Disabled
81 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)
82 |
83 |
84 | Windows
85 | true
86 |
87 |
88 |
89 |
90 | Level3
91 |
92 |
93 | MaxSpeed
94 | true
95 | true
96 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
97 |
98 |
99 | Windows
100 | true
101 | true
102 | true
103 |
104 |
105 |
106 |
107 |
108 |
--------------------------------------------------------------------------------
/SoundTouch/SoundTouch.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
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 |
--------------------------------------------------------------------------------
/SoundTouch/TDStretch.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo
4 | /// while maintaining the original pitch by using a time domain WSOLA-like method
5 | /// with several performance-increasing tweaks.
6 | ///
7 | /// Note : MMX/SSE optimized functions reside in separate, platform-specific files
8 | /// 'mmx_optimized.cpp' and 'sse_optimized.cpp'
9 | ///
10 | /// Author : Copyright (c) Olli Parviainen
11 | /// Author e-mail : oparviai 'at' iki.fi
12 | /// SoundTouch WWW: http://www.surina.net/soundtouch
13 | ///
14 | ////////////////////////////////////////////////////////////////////////////////
15 | //
16 | // Last changed : $Date: 2015-08-09 00:00:15 +0300 (Sun, 09 Aug 2015) $
17 | // File revision : $Revision: 4 $
18 | //
19 | // $Id: TDStretch.h 226 2015-08-08 21:00:15Z oparviai $
20 | //
21 | ////////////////////////////////////////////////////////////////////////////////
22 | //
23 | // License :
24 | //
25 | // SoundTouch audio processing library
26 | // Copyright (c) Olli Parviainen
27 | //
28 | // This library is free software; you can redistribute it and/or
29 | // modify it under the terms of the GNU Lesser General Public
30 | // License as published by the Free Software Foundation; either
31 | // version 2.1 of the License, or (at your option) any later version.
32 | //
33 | // This library is distributed in the hope that it will be useful,
34 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
35 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
36 | // Lesser General Public License for more details.
37 | //
38 | // You should have received a copy of the GNU Lesser General Public
39 | // License along with this library; if not, write to the Free Software
40 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
41 | //
42 | ////////////////////////////////////////////////////////////////////////////////
43 |
44 | #ifndef TDStretch_H
45 | #define TDStretch_H
46 |
47 | #include
48 | #include "STTypes.h"
49 | #include "RateTransposer.h"
50 | #include "FIFOSamplePipe.h"
51 |
52 | namespace soundtouch
53 | {
54 |
55 | /// Default values for sound processing parameters:
56 | /// Notice that the default parameters are tuned for contemporary popular music
57 | /// processing. For speech processing applications these parameters suit better:
58 | /// #define DEFAULT_SEQUENCE_MS 40
59 | /// #define DEFAULT_SEEKWINDOW_MS 15
60 | /// #define DEFAULT_OVERLAP_MS 8
61 | ///
62 |
63 | /// Default length of a single processing sequence, in milliseconds. This determines to how
64 | /// long sequences the original sound is chopped in the time-stretch algorithm.
65 | ///
66 | /// The larger this value is, the lesser sequences are used in processing. In principle
67 | /// a bigger value sounds better when slowing down tempo, but worse when increasing tempo
68 | /// and vice versa.
69 | ///
70 | /// Increasing this value reduces computational burden & vice versa.
71 | //#define DEFAULT_SEQUENCE_MS 40
72 | #define DEFAULT_SEQUENCE_MS USE_AUTO_SEQUENCE_LEN
73 |
74 | /// Giving this value for the sequence length sets automatic parameter value
75 | /// according to tempo setting (recommended)
76 | #define USE_AUTO_SEQUENCE_LEN 0
77 |
78 | /// Seeking window default length in milliseconds for algorithm that finds the best possible
79 | /// overlapping location. This determines from how wide window the algorithm may look for an
80 | /// optimal joining location when mixing the sound sequences back together.
81 | ///
82 | /// The bigger this window setting is, the higher the possibility to find a better mixing
83 | /// position will become, but at the same time large values may cause a "drifting" artifact
84 | /// because consequent sequences will be taken at more uneven intervals.
85 | ///
86 | /// If there's a disturbing artifact that sounds as if a constant frequency was drifting
87 | /// around, try reducing this setting.
88 | ///
89 | /// Increasing this value increases computational burden & vice versa.
90 | //#define DEFAULT_SEEKWINDOW_MS 15
91 | #define DEFAULT_SEEKWINDOW_MS USE_AUTO_SEEKWINDOW_LEN
92 |
93 | /// Giving this value for the seek window length sets automatic parameter value
94 | /// according to tempo setting (recommended)
95 | #define USE_AUTO_SEEKWINDOW_LEN 0
96 |
97 | /// Overlap length in milliseconds. When the chopped sound sequences are mixed back together,
98 | /// to form a continuous sound stream, this parameter defines over how long period the two
99 | /// consecutive sequences are let to overlap each other.
100 | ///
101 | /// This shouldn't be that critical parameter. If you reduce the DEFAULT_SEQUENCE_MS setting
102 | /// by a large amount, you might wish to try a smaller value on this.
103 | ///
104 | /// Increasing this value increases computational burden & vice versa.
105 | #define DEFAULT_OVERLAP_MS 8
106 |
107 |
108 | /// Class that does the time-stretch (tempo change) effect for the processed
109 | /// sound.
110 | class TDStretch : public FIFOProcessor
111 | {
112 | protected:
113 | int channels;
114 | int sampleReq;
115 |
116 | int overlapLength;
117 | int seekLength;
118 | int seekWindowLength;
119 | int overlapDividerBitsNorm;
120 | int overlapDividerBitsPure;
121 | int slopingDivider;
122 | int sampleRate;
123 | int sequenceMs;
124 | int seekWindowMs;
125 | int overlapMs;
126 |
127 | unsigned long maxnorm;
128 | float maxnormf;
129 |
130 | double tempo;
131 | double nominalSkip;
132 | double skipFract;
133 |
134 | bool bQuickSeek;
135 | bool bAutoSeqSetting;
136 | bool bAutoSeekSetting;
137 |
138 | SAMPLETYPE *pMidBuffer;
139 | SAMPLETYPE *pMidBufferUnaligned;
140 |
141 | FIFOSampleBuffer outputBuffer;
142 | FIFOSampleBuffer inputBuffer;
143 |
144 | void acceptNewOverlapLength(int newOverlapLength);
145 |
146 | virtual void clearCrossCorrState();
147 | void calculateOverlapLength(int overlapMs);
148 |
149 | virtual double calcCrossCorr(const SAMPLETYPE *mixingPos, const SAMPLETYPE *compare, double &norm);
150 | virtual double calcCrossCorrAccumulate(const SAMPLETYPE *mixingPos, const SAMPLETYPE *compare, double &norm);
151 |
152 | virtual int seekBestOverlapPositionFull(const SAMPLETYPE *refPos);
153 | virtual int seekBestOverlapPositionQuick(const SAMPLETYPE *refPos);
154 | virtual int seekBestOverlapPosition(const SAMPLETYPE *refPos);
155 |
156 | virtual void overlapStereo(SAMPLETYPE *output, const SAMPLETYPE *input) const;
157 | virtual void overlapMono(SAMPLETYPE *output, const SAMPLETYPE *input) const;
158 | virtual void overlapMulti(SAMPLETYPE *output, const SAMPLETYPE *input) const;
159 |
160 | void clearMidBuffer();
161 | void overlap(SAMPLETYPE *output, const SAMPLETYPE *input, uint ovlPos) const;
162 |
163 | void calcSeqParameters();
164 | void adaptNormalizer();
165 |
166 |
167 | /// Changes the tempo of the given sound samples.
168 | /// Returns amount of samples returned in the "output" buffer.
169 | /// The maximum amount of samples that can be returned at a time is set by
170 | /// the 'set_returnBuffer_size' function.
171 | void processSamples();
172 |
173 | public:
174 | TDStretch();
175 | virtual ~TDStretch();
176 |
177 | /// Operator 'new' is overloaded so that it automatically creates a suitable instance
178 | /// depending on if we've a MMX/SSE/etc-capable CPU available or not.
179 | static void *operator new(size_t s);
180 |
181 | /// Use this function instead of "new" operator to create a new instance of this class.
182 | /// This function automatically chooses a correct feature set depending on if the CPU
183 | /// supports MMX/SSE/etc extensions.
184 | static TDStretch *newInstance();
185 |
186 | /// Returns the output buffer object
187 | FIFOSamplePipe *getOutput() { return &outputBuffer; };
188 |
189 | /// Returns the input buffer object
190 | FIFOSamplePipe *getInput() { return &inputBuffer; };
191 |
192 | /// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower
193 | /// tempo, larger faster tempo.
194 | void setTempo(double newTempo);
195 |
196 | /// Returns nonzero if there aren't any samples available for outputting.
197 | virtual void clear();
198 |
199 | /// Clears the input buffer
200 | void clearInput();
201 |
202 | /// Sets the number of channels, 1 = mono, 2 = stereo
203 | void setChannels(int numChannels);
204 |
205 | /// Enables/disables the quick position seeking algorithm. Zero to disable,
206 | /// nonzero to enable
207 | void enableQuickSeek(bool enable);
208 |
209 | /// Returns nonzero if the quick seeking algorithm is enabled.
210 | bool isQuickSeekEnabled() const;
211 |
212 | /// Sets routine control parameters. These control are certain time constants
213 | /// defining how the sound is stretched to the desired duration.
214 | //
215 | /// 'sampleRate' = sample rate of the sound
216 | /// 'sequenceMS' = one processing sequence length in milliseconds
217 | /// 'seekwindowMS' = seeking window length for scanning the best overlapping
218 | /// position
219 | /// 'overlapMS' = overlapping length
220 | void setParameters(int sampleRate, ///< Samplerate of sound being processed (Hz)
221 | int sequenceMS = -1, ///< Single processing sequence length (ms)
222 | int seekwindowMS = -1, ///< Offset seeking window length (ms)
223 | int overlapMS = -1 ///< Sequence overlapping length (ms)
224 | );
225 |
226 | /// Get routine control parameters, see setParameters() function.
227 | /// Any of the parameters to this function can be NULL, in such case corresponding parameter
228 | /// value isn't returned.
229 | void getParameters(int *pSampleRate, int *pSequenceMs, int *pSeekWindowMs, int *pOverlapMs) const;
230 |
231 | /// Adds 'numsamples' pcs of samples from the 'samples' memory position into
232 | /// the input of the object.
233 | virtual void putSamples(
234 | const SAMPLETYPE *samples, ///< Input sample data
235 | uint numSamples ///< Number of samples in 'samples' so that one sample
236 | ///< contains both channels if stereo
237 | );
238 |
239 | /// return nominal input sample requirement for triggering a processing batch
240 | int getInputSampleReq() const
241 | {
242 | return (int)(nominalSkip + 0.5);
243 | }
244 |
245 | /// return nominal output sample amount when running a processing batch
246 | int getOutputBatchSize() const
247 | {
248 | return seekWindowLength - overlapLength;
249 | }
250 | };
251 |
252 |
253 |
254 | // Implementation-specific class declarations:
255 |
256 | #ifdef SOUNDTOUCH_ALLOW_MMX
257 | /// Class that implements MMX optimized routines for 16bit integer samples type.
258 | class TDStretchMMX : public TDStretch
259 | {
260 | protected:
261 | double calcCrossCorr(const short *mixingPos, const short *compare, double &norm);
262 | double calcCrossCorrAccumulate(const short *mixingPos, const short *compare, double &norm);
263 | virtual void overlapStereo(short *output, const short *input) const;
264 | virtual void clearCrossCorrState();
265 | };
266 | #endif /// SOUNDTOUCH_ALLOW_MMX
267 |
268 |
269 | #ifdef SOUNDTOUCH_ALLOW_SSE
270 | /// Class that implements SSE optimized routines for floating point samples type.
271 | class TDStretchSSE : public TDStretch
272 | {
273 | protected:
274 | double calcCrossCorr(const float *mixingPos, const float *compare, double &norm);
275 | double calcCrossCorrAccumulate(const float *mixingPos, const float *compare, double &norm);
276 | };
277 |
278 | #endif /// SOUNDTOUCH_ALLOW_SSE
279 |
280 | }
281 | #endif /// TDStretch_H
282 |
--------------------------------------------------------------------------------
/SoundTouch/cpu_detect.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// A header file for detecting the Intel MMX instructions set extension.
4 | ///
5 | /// Please see 'mmx_win.cpp', 'mmx_cpp.cpp' and 'mmx_non_x86.cpp' for the
6 | /// routine implementations for x86 Windows, x86 gnu version and non-x86
7 | /// platforms, respectively.
8 | ///
9 | /// Author : Copyright (c) Olli Parviainen
10 | /// Author e-mail : oparviai 'at' iki.fi
11 | /// SoundTouch WWW: http://www.surina.net/soundtouch
12 | ///
13 | ////////////////////////////////////////////////////////////////////////////////
14 | //
15 | // Last changed : $Date: 2008-02-10 18:26:55 +0200 (Sun, 10 Feb 2008) $
16 | // File revision : $Revision: 4 $
17 | //
18 | // $Id: cpu_detect.h 11 2008-02-10 16:26:55Z oparviai $
19 | //
20 | ////////////////////////////////////////////////////////////////////////////////
21 | //
22 | // License :
23 | //
24 | // SoundTouch audio processing library
25 | // Copyright (c) Olli Parviainen
26 | //
27 | // This library is free software; you can redistribute it and/or
28 | // modify it under the terms of the GNU Lesser General Public
29 | // License as published by the Free Software Foundation; either
30 | // version 2.1 of the License, or (at your option) any later version.
31 | //
32 | // This library is distributed in the hope that it will be useful,
33 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
34 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
35 | // Lesser General Public License for more details.
36 | //
37 | // You should have received a copy of the GNU Lesser General Public
38 | // License along with this library; if not, write to the Free Software
39 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
40 | //
41 | ////////////////////////////////////////////////////////////////////////////////
42 |
43 | #ifndef _CPU_DETECT_H_
44 | #define _CPU_DETECT_H_
45 |
46 | #include "STTypes.h"
47 |
48 | #define SUPPORT_MMX 0x0001
49 | #define SUPPORT_3DNOW 0x0002
50 | #define SUPPORT_ALTIVEC 0x0004
51 | #define SUPPORT_SSE 0x0008
52 | #define SUPPORT_SSE2 0x0010
53 |
54 | /// Checks which instruction set extensions are supported by the CPU.
55 | ///
56 | /// \return A bitmask of supported extensions, see SUPPORT_... defines.
57 | uint detectCPUextensions(void);
58 |
59 | /// Disables given set of instruction extensions. See SUPPORT_... defines.
60 | void disableExtensions(uint wDisableMask);
61 |
62 | #endif // _CPU_DETECT_H_
63 |
--------------------------------------------------------------------------------
/SoundTouch/cpu_detect_x86.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Generic version of the x86 CPU extension detection routine.
4 | ///
5 | /// This file is for GNU & other non-Windows compilers, see 'cpu_detect_x86_win.cpp'
6 | /// for the Microsoft compiler version.
7 | ///
8 | /// Author : Copyright (c) Olli Parviainen
9 | /// Author e-mail : oparviai 'at' iki.fi
10 | /// SoundTouch WWW: http://www.surina.net/soundtouch
11 | ///
12 | ////////////////////////////////////////////////////////////////////////////////
13 | //
14 | // Last changed : $Date: 2014-01-07 20:24:28 +0200 (Tue, 07 Jan 2014) $
15 | // File revision : $Revision: 4 $
16 | //
17 | // $Id: cpu_detect_x86.cpp 183 2014-01-07 18:24:28Z oparviai $
18 | //
19 | ////////////////////////////////////////////////////////////////////////////////
20 | //
21 | // License :
22 | //
23 | // SoundTouch audio processing library
24 | // Copyright (c) Olli Parviainen
25 | //
26 | // This library is free software; you can redistribute it and/or
27 | // modify it under the terms of the GNU Lesser General Public
28 | // License as published by the Free Software Foundation; either
29 | // version 2.1 of the License, or (at your option) any later version.
30 | //
31 | // This library is distributed in the hope that it will be useful,
32 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
33 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34 | // Lesser General Public License for more details.
35 | //
36 | // You should have received a copy of the GNU Lesser General Public
37 | // License along with this library; if not, write to the Free Software
38 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39 | //
40 | ////////////////////////////////////////////////////////////////////////////////
41 |
42 | #include "cpu_detect.h"
43 | #include "STTypes.h"
44 |
45 |
46 | #if defined(SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS)
47 |
48 | #if defined(__GNUC__) && defined(__i386__)
49 | // gcc
50 | #include "cpuid.h"
51 | #elif defined(_M_IX86)
52 | // windows non-gcc
53 | #include
54 | #endif
55 |
56 | #define bit_MMX (1 << 23)
57 | #define bit_SSE (1 << 25)
58 | #define bit_SSE2 (1 << 26)
59 | #endif
60 |
61 |
62 | //////////////////////////////////////////////////////////////////////////////
63 | //
64 | // processor instructions extension detection routines
65 | //
66 | //////////////////////////////////////////////////////////////////////////////
67 |
68 | // Flag variable indicating whick ISA extensions are disabled (for debugging)
69 | static uint _dwDisabledISA = 0x00; // 0xffffffff; //<- use this to disable all extensions
70 |
71 | // Disables given set of instruction extensions. See SUPPORT_... defines.
72 | void disableExtensions(uint dwDisableMask)
73 | {
74 | _dwDisabledISA = dwDisableMask;
75 | }
76 |
77 |
78 |
79 | /// Checks which instruction set extensions are supported by the CPU.
80 | uint detectCPUextensions(void)
81 | {
82 | /// If building for a 64bit system (no Itanium) and the user wants optimizations.
83 | /// Return the OR of SUPPORT_{MMX,SSE,SSE2}. 11001 or 0x19.
84 | /// Keep the _dwDisabledISA test (2 more operations, could be eliminated).
85 | #if ((defined(__GNUC__) && defined(__x86_64__)) \
86 | || defined(_M_X64)) \
87 | && defined(SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS)
88 | return 0x19 & ~_dwDisabledISA;
89 |
90 | /// If building for a 32bit system and the user wants optimizations.
91 | /// Keep the _dwDisabledISA test (2 more operations, could be eliminated).
92 | #elif ((defined(__GNUC__) && defined(__i386__)) \
93 | || defined(_M_IX86)) \
94 | && defined(SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS)
95 |
96 | if (_dwDisabledISA == 0xffffffff) return 0;
97 |
98 | uint res = 0;
99 |
100 | #if defined(__GNUC__)
101 | // GCC version of cpuid. Requires GCC 4.3.0 or later for __cpuid intrinsic support.
102 | uint eax, ebx, ecx, edx; // unsigned int is the standard type. uint is defined by the compiler and not guaranteed to be portable.
103 |
104 | // Check if no cpuid support.
105 | if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx)) return 0; // always disable extensions.
106 |
107 | if (edx & bit_MMX) res = res | SUPPORT_MMX;
108 | if (edx & bit_SSE) res = res | SUPPORT_SSE;
109 | if (edx & bit_SSE2) res = res | SUPPORT_SSE2;
110 |
111 | #else
112 | // Window / VS version of cpuid. Notice that Visual Studio 2005 or later required
113 | // for __cpuid intrinsic support.
114 | int reg[4] = {-1};
115 |
116 | // Check if no cpuid support.
117 | __cpuid(reg,0);
118 | if ((unsigned int)reg[0] == 0) return 0; // always disable extensions.
119 |
120 | __cpuid(reg,1);
121 | if ((unsigned int)reg[3] & bit_MMX) res = res | SUPPORT_MMX;
122 | if ((unsigned int)reg[3] & bit_SSE) res = res | SUPPORT_SSE;
123 | if ((unsigned int)reg[3] & bit_SSE2) res = res | SUPPORT_SSE2;
124 |
125 | #endif
126 |
127 | return res & ~_dwDisabledISA;
128 |
129 | #else
130 |
131 | /// One of these is true:
132 | /// 1) We don't want optimizations.
133 | /// 2) Using an unsupported compiler.
134 | /// 3) Running on a non-x86 platform.
135 | return 0;
136 |
137 | #endif
138 | }
139 |
--------------------------------------------------------------------------------
/wav_sound/MediaInfo.cpp:
--------------------------------------------------------------------------------
1 | #include "MediaInfo.h"
2 |
3 |
4 | CMediaInfo::CMediaInfo()
5 | {
6 | type = MEDIA_TYPE::NONE;
7 |
8 | pFormatContext = nullptr;
9 |
10 | pVideo_codec_context = nullptr;
11 | pAudio_codec_context = nullptr;
12 |
13 | video_stream_index = -1;
14 | audio_stream_index = -1;
15 | }
16 |
17 | CMediaInfo::CMediaInfo(MEDIA_TYPE media)
18 | :type(media)
19 | {
20 | pFormatContext = nullptr;
21 |
22 | pVideo_codec_context = nullptr;
23 | pAudio_codec_context = nullptr;
24 |
25 | video_stream_index = -1;
26 | audio_stream_index = -1;
27 | }
28 |
29 |
30 | CMediaInfo::~CMediaInfo()
31 | {
32 | if (pFormatContext)
33 | {
34 | avformat_close_input(&pFormatContext);
35 | pFormatContext = nullptr;
36 | }
37 |
38 | if (pAudio_codec_context)
39 | {
40 | avcodec_close(pAudio_codec_context);
41 | pAudio_codec_context = nullptr;
42 | }
43 |
44 | if (pVideo_codec_context)
45 | {
46 | avcodec_close(pVideo_codec_context);
47 | pVideo_codec_context = nullptr;
48 | }
49 | }
50 |
51 | ERROR_TYPE CMediaInfo::open(const char *filename)
52 | {
53 | if (type == MEDIA_TYPE::NONE)
54 | return ERROR_TYPE::MISS_TYPE;
55 |
56 | av_register_all();
57 |
58 | if (avformat_open_input(&pFormatContext, filename, nullptr, nullptr) < 0)
59 | return ERROR_TYPE::OPEN;
60 |
61 | if (avformat_find_stream_info(pFormatContext, nullptr) < 0)
62 | return ERROR_TYPE::STREAM_INFO;
63 |
64 | #ifdef _DEBUG
65 | av_dump_format(pFormatContext, 0, filename, 0);
66 | #endif
67 |
68 | // Find stream index
69 | for (size_t i = 0; i < pFormatContext->nb_streams; i++)
70 | {
71 | if ((type == MEDIA_TYPE::ALL || type == MEDIA_TYPE::AUDIO) &&
72 | pFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
73 | audio_stream_index < 0)
74 |
75 | audio_stream_index = i;
76 |
77 | if ((type == MEDIA_TYPE::ALL || type == MEDIA_TYPE::VIDEO) &&
78 | pFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
79 | video_stream_index < 0)
80 |
81 | video_stream_index = i;
82 | }
83 |
84 | // Video and audio
85 | if (type == MEDIA_TYPE::ALL)
86 | {
87 | if (audio_stream_index < 0)
88 | return ERROR_TYPE::AUDIO_STREAM;
89 | if (video_stream_index < 0)
90 | return ERROR_TYPE::VIDEO_STREAM;
91 |
92 | // Open audio codec context
93 | AVCodec *pAudio_codec = avcodec_find_decoder(pFormatContext->streams[audio_stream_index]->codecpar->codec_id);
94 | if (!pAudio_codec)
95 | return ERROR_TYPE::AUDIO_CODEC;
96 |
97 | pAudio_codec_context = avcodec_alloc_context3(pAudio_codec);
98 | //avcodec_copy_context(pAudio_codec_context, pFormatContext->streams[audio_stream_index]->codec);
99 |
100 | avcodec_parameters_to_context(pAudio_codec_context, pFormatContext->streams[audio_stream_index]->codecpar);
101 | if (avcodec_open2(pAudio_codec_context, pAudio_codec, nullptr) < 0)
102 | return ERROR_TYPE::AUDIO_CODEC_OPEN;
103 |
104 | // Open video codec context
105 | AVCodec *pVideo_codec = avcodec_find_decoder(pFormatContext->streams[video_stream_index]->codecpar->codec_id);
106 | if (!pVideo_codec)
107 | return ERROR_TYPE::VIDEO_CODEC;
108 |
109 | pVideo_codec_context = avcodec_alloc_context3(pVideo_codec);
110 | avcodec_parameters_to_context(pVideo_codec_context, pFormatContext->streams[video_stream_index]->codecpar);
111 |
112 | if (avcodec_open2(pVideo_codec_context, pVideo_codec, nullptr) < 0)
113 | return ERROR_TYPE::VIDEO_CODEC_OPEN;
114 |
115 | return ERROR_TYPE::OK;
116 | }
117 |
118 | // Only video
119 | if (type == MEDIA_TYPE::VIDEO)
120 | {
121 | if (video_stream_index < 0)
122 | return ERROR_TYPE::VIDEO_STREAM;
123 |
124 | // Open video codec context
125 | AVCodec *pVideo_codec = avcodec_find_decoder(pFormatContext->streams[video_stream_index]->codecpar->codec_id);
126 | if (!pVideo_codec)
127 | return ERROR_TYPE::VIDEO_CODEC;
128 |
129 | pVideo_codec_context = avcodec_alloc_context3(pVideo_codec);
130 | avcodec_parameters_to_context(pVideo_codec_context, pFormatContext->streams[video_stream_index]->codecpar);
131 |
132 | if (avcodec_open2(pVideo_codec_context, pVideo_codec, nullptr) < 0)
133 | return ERROR_TYPE::VIDEO_CODEC_OPEN;
134 |
135 | return ERROR_TYPE::OK;
136 | }
137 |
138 | // Only audio
139 | if (type == MEDIA_TYPE::AUDIO)
140 | {
141 | if (audio_stream_index < 0)
142 | return ERROR_TYPE::AUDIO_STREAM;
143 |
144 | // Open audio codec context
145 | AVCodec *pAudio_codec = avcodec_find_decoder(pFormatContext->streams[audio_stream_index]->codecpar->codec_id);
146 | if (!pAudio_codec)
147 | return ERROR_TYPE::AUDIO_CODEC;
148 |
149 | pAudio_codec_context = avcodec_alloc_context3(pAudio_codec);
150 | avcodec_parameters_to_context(pAudio_codec_context, pFormatContext->streams[audio_stream_index]->codecpar);
151 |
152 | if (avcodec_open2(pAudio_codec_context, pAudio_codec, nullptr) < 0)
153 | return ERROR_TYPE::AUDIO_CODEC_OPEN;
154 |
155 | return ERROR_TYPE::OK;
156 | }
157 |
158 | return ERROR_TYPE::OK;
159 | }
160 |
161 | void CMediaInfo::close()
162 | {
163 | if (pFormatContext)
164 | {
165 | avformat_close_input(&pFormatContext);
166 | pFormatContext = nullptr;
167 | }
168 |
169 | if (pAudio_codec_context)
170 | {
171 | avcodec_free_context(&pAudio_codec_context);
172 | pAudio_codec_context = nullptr;
173 | }
174 |
175 | if (pVideo_codec_context)
176 | {
177 | avcodec_free_context(&pVideo_codec_context);
178 | pVideo_codec_context = nullptr;
179 | }
180 |
181 | type = MEDIA_TYPE::NONE;
182 | video_stream_index = -1;
183 | audio_stream_index = -1;
184 | }
185 |
186 | void CMediaInfo::error_message(ERROR_TYPE error)
187 | {
188 | switch (error)
189 | {
190 | case ERROR_TYPE::OPEN:
191 | std::cerr << "Could not open the media file" << std::endl;
192 | break;
193 |
194 | case ERROR_TYPE::STREAM_INFO:
195 | std::cerr << "Could not find the stream info." << std::endl;
196 | break;
197 |
198 | case ERROR_TYPE::AUDIO_STREAM:
199 | std::cerr << "Could not find the index of audio stream." << std::endl;
200 | break;
201 |
202 | case ERROR_TYPE::VIDEO_STREAM:
203 | std::cerr << "Could not find the index of video stream." << std::endl;
204 | break;
205 |
206 | case ERROR_TYPE::VIDEO_CODEC:
207 | std::cerr << "Could not find the video CODEC." << std::endl;
208 | break;
209 |
210 | case ERROR_TYPE::AUDIO_CODEC:
211 | std::cerr << "Could not find the audio CODEC." << std::endl;
212 | break;
213 |
214 | case ERROR_TYPE::AUDIO_CODEC_OPEN:
215 | std::cerr << "Could not open the audio CODEC context." << std::endl;
216 | break;
217 |
218 | case ERROR_TYPE::VIDEO_CODEC_OPEN:
219 | std::cerr << "Could not open the video CODEC context." << std::endl;
220 | break;
221 |
222 | case ERROR_TYPE::MISS_TYPE:
223 | std::cerr << "Miss the media type." << std::endl;
224 | break;
225 | }
226 | }
227 |
--------------------------------------------------------------------------------
/wav_sound/MediaInfo.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | extern "C" {
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | }
13 |
14 | enum MEDIA_TYPE
15 | {
16 | NONE,
17 | VIDEO, // Only video infomation
18 | AUDIO, // Only audio infomation
19 | ALL // Video and audio infomation
20 | };
21 |
22 | enum ERROR_TYPE
23 | {
24 | OPEN, // Open input failed
25 | STREAM_INFO, // Couldn't find stream info
26 | AUDIO_STREAM, // Couldn't find audio stream index
27 | VIDEO_STREAM, // Couldn't find video stream index
28 | AUDIO_CODEC, // Couldn't find audio codec
29 | VIDEO_CODEC, // Couldn't find video codec
30 | AUDIO_CODEC_OPEN, // Open audio codec context failed
31 | VIDEO_CODEC_OPEN, // Open video codec context failed
32 | MISS_TYPE, // Miss the media type
33 | OK // Succes
34 | };
35 |
36 | class CMediaInfo
37 | {
38 |
39 | public:
40 | CMediaInfo();
41 | CMediaInfo(MEDIA_TYPE media);
42 | ~CMediaInfo();
43 |
44 | public:
45 | ERROR_TYPE open(const char *filename);
46 | void close();
47 | void error_message(ERROR_TYPE error);
48 |
49 | public:
50 | MEDIA_TYPE type;
51 | AVFormatContext *pFormatContext;
52 |
53 | AVCodecContext *pVideo_codec_context;
54 | AVCodecContext *pAudio_codec_context;
55 |
56 | int video_stream_index;
57 | int audio_stream_index;
58 | };
59 |
60 |
--------------------------------------------------------------------------------
/wav_sound/Wav.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brookicv/Sample/1befa744304038ee5c5035a5dc9bd2093b419649/wav_sound/Wav.h
--------------------------------------------------------------------------------
/wav_sound/main.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brookicv/Sample/1befa744304038ee5c5035a5dc9bd2093b419649/wav_sound/main.cpp
--------------------------------------------------------------------------------
/wav_sound/wav_sound.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | {0466CAD9-52B6-4F1C-85C7-AD43294B4C93}
23 | Win32Proj
24 | wav_sound
25 |
26 |
27 |
28 | Application
29 | true
30 | v120
31 | Unicode
32 |
33 |
34 | Application
35 | false
36 | v120
37 | true
38 | Unicode
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | true
53 |
54 |
55 | false
56 |
57 |
58 |
59 |
60 |
61 | Level3
62 | Disabled
63 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
64 |
65 |
66 | Console
67 | true
68 |
69 |
70 |
71 |
72 | Level3
73 |
74 |
75 | MaxSpeed
76 | true
77 | true
78 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
79 |
80 |
81 | Console
82 | true
83 | true
84 | true
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/wav_sound/wav_sound.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | 源文件
20 |
21 |
22 | 源文件
23 |
24 |
25 |
26 |
27 | 头文件
28 |
29 |
30 | 头文件
31 |
32 |
33 |
--------------------------------------------------------------------------------