├── .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 | --------------------------------------------------------------------------------