├── a.wav ├── README.md ├── noiseReduction ├── noiseReduction.xcodeproj │ ├── xcuserdata │ │ ├── LJP.xcuserdatad │ │ │ ├── xcdebugger │ │ │ │ └── Breakpoints_v2.xcbkptlist │ │ │ └── xcschemes │ │ │ │ └── xcschememanagement.plist │ │ └── dengsir.xcuserdatad │ │ │ └── xcschemes │ │ │ └── xcschememanagement.plist │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcuserdata │ │ │ ├── LJP.xcuserdatad │ │ │ │ └── UserInterfaceState.xcuserstate │ │ │ └── dengsir.xcuserdatad │ │ │ │ └── UserInterfaceState.xcuserstate │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── project.pbxproj ├── noiseReduction │ ├── ViewController.h │ ├── AppDelegate.h │ ├── main.m │ ├── Info.plist │ ├── SDK │ │ ├── timing.h │ │ ├── noise_suppression.h │ │ └── noise_suppression.c │ ├── Base.lproj │ │ ├── Main.storyboard │ │ └── LaunchScreen.storyboard │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── AppDelegate.m │ └── ViewController.m ├── noiseReductionTests │ ├── Info.plist │ └── noiseReductionTests.m └── noiseReductionUITests │ ├── Info.plist │ └── noiseReductionUITests.m └── .gitignore /a.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lijingpei2016/noiseReduction/HEAD/a.wav -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # noiseReduction 2 | 基于WebRTC实现iOS端音频降噪功能 3 | 4 | 使用方法: 5 | 配置好路径就ok 6 | NSString * inpath = @“/ Users / apple / Desktop / a.wav; 7 | NSString *outpath = @"/Users/apple/Desktop/b.wav"; 8 | -------------------------------------------------------------------------------- /noiseReduction/noiseReduction.xcodeproj/xcuserdata/LJP.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /noiseReduction/noiseReduction.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /noiseReduction/noiseReduction.xcodeproj/project.xcworkspace/xcuserdata/LJP.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lijingpei2016/noiseReduction/HEAD/noiseReduction/noiseReduction.xcodeproj/project.xcworkspace/xcuserdata/LJP.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /noiseReduction/noiseReduction.xcodeproj/project.xcworkspace/xcuserdata/dengsir.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lijingpei2016/noiseReduction/HEAD/noiseReduction/noiseReduction.xcodeproj/project.xcworkspace/xcuserdata/dengsir.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /noiseReduction/noiseReduction/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // noiseReduction 4 | // 5 | // Created by LJP on 2018/8/23. 6 | // Copyright © 2018 LJP. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /noiseReduction/noiseReduction.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /noiseReduction/noiseReduction/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // noiseReduction 4 | // 5 | // Created by LJP on 2018/8/23. 6 | // Copyright © 2018 LJP. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /noiseReduction/noiseReduction/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // noiseReduction 4 | // 5 | // Created by LJP on 2018/8/23. 6 | // Copyright © 2018 LJP. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /noiseReduction/noiseReduction.xcodeproj/xcuserdata/LJP.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | noiseReduction.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /noiseReduction/noiseReduction.xcodeproj/xcuserdata/dengsir.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | noiseReduction.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /noiseReduction/noiseReductionTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /noiseReduction/noiseReductionUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /noiseReduction/noiseReductionTests/noiseReductionTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // noiseReductionTests.m 3 | // noiseReductionTests 4 | // 5 | // Created by LJP on 2018/8/23. 6 | // Copyright © 2018 LJP. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface noiseReductionTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation noiseReductionTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /noiseReduction/noiseReductionUITests/noiseReductionUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // noiseReductionUITests.m 3 | // noiseReductionUITests 4 | // 5 | // Created by LJP on 2018/8/23. 6 | // Copyright © 2018 LJP. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface noiseReductionUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation noiseReductionUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | # CocoaPods 32 | # 33 | # We recommend against adding the Pods directory to your .gitignore. However 34 | # you should judge for yourself, the pros and cons are mentioned at: 35 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 36 | # 37 | # Pods/ 38 | 39 | # Carthage 40 | # 41 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 42 | # Carthage/Checkouts 43 | 44 | Carthage/Build 45 | 46 | # fastlane 47 | # 48 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 49 | # screenshots whenever they are needed. 50 | # For more information about the recommended setup visit: 51 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 52 | 53 | fastlane/report.xml 54 | fastlane/Preview.html 55 | fastlane/screenshots/**/*.png 56 | fastlane/test_output 57 | 58 | # Code Injection 59 | # 60 | # After new code Injection tools there's a generated folder /iOSInjectionProject 61 | # https://github.com/johnno1962/injectionforxcode 62 | 63 | iOSInjectionProject/ 64 | -------------------------------------------------------------------------------- /noiseReduction/noiseReduction/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /noiseReduction/noiseReduction/SDK/timing.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #if defined(__APPLE__) 5 | # include 6 | #elif defined(_WIN32) 7 | # define WIN32_LEAN_AND_MEAN 8 | 9 | # include 10 | 11 | #else // __linux 12 | 13 | # include 14 | 15 | # ifndef CLOCK_MONOTONIC //_RAW 16 | # define CLOCK_MONOTONIC CLOCK_REALTIME 17 | # endif 18 | #endif 19 | 20 | static 21 | uint64_t nanotimer() { 22 | static int ever = 0; 23 | #if defined(__APPLE__) 24 | static mach_timebase_info_data_t frequency; 25 | if (!ever) { 26 | if (mach_timebase_info(&frequency) != KERN_SUCCESS) { 27 | return 0; 28 | } 29 | ever = 1; 30 | } 31 | return (mach_absolute_time() * frequency.numer / frequency.denom); 32 | #elif defined(_WIN32) 33 | static LARGE_INTEGER frequency; 34 | if (!ever) { 35 | QueryPerformanceFrequency(&frequency); 36 | ever = 1; 37 | } 38 | LARGE_INTEGER t; 39 | QueryPerformanceCounter(&t); 40 | return (t.QuadPart * (uint64_t) 1e9) / frequency.QuadPart; 41 | #else // __linux 42 | struct timespec t; 43 | if (!ever) { 44 | if (clock_gettime(CLOCK_MONOTONIC, &t) != 0) { 45 | return 0; 46 | } 47 | ever = 1; 48 | } 49 | clock_gettime(CLOCK_MONOTONIC, &t); 50 | return (t.tv_sec * (uint64_t) 1e9) + t.tv_nsec; 51 | #endif 52 | } 53 | 54 | 55 | static double now() { 56 | static uint64_t epoch = 0; 57 | if (!epoch) { 58 | epoch = nanotimer(); 59 | } 60 | return (nanotimer() - epoch) / 1e9; 61 | }; 62 | 63 | double calcElapsed(double start, double end) { 64 | double took = -start; 65 | return took + end; 66 | } -------------------------------------------------------------------------------- /noiseReduction/noiseReduction/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /noiseReduction/noiseReduction/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /noiseReduction/noiseReduction/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /noiseReduction/noiseReduction/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // noiseReduction 4 | // 5 | // Created by LJP on 2018/8/23. 6 | // Copyright © 2018 LJP. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /noiseReduction/noiseReduction/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // noiseReduction 4 | // 5 | // Created by LJP on 2018/8/23. 6 | // Copyright © 2018 LJP. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | #define DR_WAV_IMPLEMENTATION 12 | 13 | #include "dr_wav.h" 14 | #include "timing.h" 15 | #include "noise_suppression.h" 16 | 17 | #ifndef nullptr 18 | #define nullptr 0 19 | #endif 20 | 21 | #ifndef MIN 22 | #define MIN(A, B) ((A) < (B) ? (A) : (B)) 23 | #endif 24 | 25 | enum nsLevel { 26 | kLow, 27 | kModerate, 28 | kHigh, 29 | kVeryHigh 30 | }; 31 | 32 | @interface ViewController () 33 | 34 | @end 35 | 36 | @implementation ViewController 37 | 38 | - (void)viewDidLoad { 39 | 40 | [super viewDidLoad]; 41 | 42 | NSString *inpath = @"/Users/apple/Desktop/a.wav"; 43 | NSString *outpath = @"/Users/apple/Desktop/b.wav"; 44 | 45 | const char *in_file = [inpath UTF8String]; 46 | const char *out_file = [outpath UTF8String]; 47 | 48 | char in_f[1024]; 49 | //把从src地址开始且含有'\0'结束符的字符串复制到以dest开始的地址空间,返回值的类型为char* 50 | strcpy(in_f,in_file); 51 | 52 | char out_f[1024]; 53 | strcpy(out_f,out_file); 54 | 55 | [self noise_suppression:in_f and:out_f]; 56 | } 57 | 58 | 59 | - (void)noise_suppression:(char *)in_file and:(char *)out_file { 60 | //音频采样率 61 | uint32_t sampleRate = 0; 62 | //总音频采样数 63 | uint64_t inSampleCount = 0; 64 | 65 | int16_t *inBuffer = [self wavRead_int16:in_file :&sampleRate :&inSampleCount]; 66 | 67 | //如果加载成功 68 | if (inBuffer != nullptr) { 69 | double startTime = now(); 70 | [self nsProcess:inBuffer :sampleRate :(int)inSampleCount :kModerate]; 71 | double time_interval = calcElapsed(startTime, now()); 72 | printf("time interval: %d ms\n ", (int) (time_interval * 1000)); 73 | [self wavWrite_int16:out_file :inBuffer :sampleRate :inSampleCount]; 74 | free(inBuffer); 75 | } 76 | } 77 | 78 | //写wav文件 79 | - (void)wavWrite_int16:(char *)filename :(int16_t *)buffer :(size_t)sampleRate :(size_t)totalSampleCount { 80 | drwav_data_format format = {}; 81 | format.container = drwav_container_riff; // <-- drwav_container_riff = normal WAV files, drwav_container_w64 = Sony Wave64. 82 | format.format = DR_WAVE_FORMAT_PCM; // <-- Any of the DR_WAVE_FORMAT_* codes. 83 | format.channels = 1; 84 | format.sampleRate = (drwav_uint32)sampleRate; 85 | format.bitsPerSample = 16; 86 | drwav *pWav = drwav_open_file_write(filename, &format); 87 | if (pWav) { 88 | drwav_uint64 samplesWritten = drwav_write(pWav, totalSampleCount, buffer); 89 | drwav_uninit(pWav); 90 | if (samplesWritten != totalSampleCount) { 91 | fprintf(stderr, "ERROR\n"); 92 | exit(1); 93 | } 94 | } 95 | } 96 | 97 | //读取wav文件 98 | - (int16_t *)wavRead_int16:(char *)filename :(uint32_t *)sampleRate :(uint64_t *)totalSampleCount{ 99 | unsigned int channels; 100 | int16_t *buffer = drwav_open_and_read_file_s16(filename, &channels, sampleRate, totalSampleCount); 101 | if (buffer == nullptr) { 102 | printf("ERROR."); 103 | } 104 | return buffer; 105 | } 106 | 107 | -(int)nsProcess:(int16_t *)buffer :(uint32_t)sampleRate :(int)samplesCount :(enum nsLevel)level { 108 | if (buffer == nullptr) return -1; 109 | if (samplesCount == 0) return -1; 110 | size_t samples = MIN(160, sampleRate / 100); 111 | if (samples == 0) return -1; 112 | uint32_t num_bands = 1; 113 | int16_t *input = buffer; 114 | size_t nTotal = (samplesCount / samples); 115 | NsHandle *nsHandle = WebRtcNs_Create(); 116 | int status = WebRtcNs_Init(nsHandle, sampleRate); 117 | if (status != 0) { 118 | printf("WebRtcNs_Init fail\n"); 119 | return -1; 120 | } 121 | status = WebRtcNs_set_policy(nsHandle, level); 122 | if (status != 0) { 123 | printf("WebRtcNs_set_policy fail\n"); 124 | return -1; 125 | } 126 | for (int i = 0; i < nTotal; i++) { 127 | int16_t *nsIn[1] = {input}; //ns input[band][data] 128 | int16_t *nsOut[1] = {input}; //ns output[band][data] 129 | WebRtcNs_Analyze(nsHandle, nsIn[0]); 130 | WebRtcNs_Process(nsHandle, (const int16_t *const *) nsIn, num_bands, nsOut); 131 | input += samples; 132 | } 133 | WebRtcNs_Free(nsHandle); 134 | 135 | return 1; 136 | } 137 | 138 | 139 | @end 140 | -------------------------------------------------------------------------------- /noiseReduction/noiseReduction/SDK/noise_suppression.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | #ifndef WEBRTC_MODULES_AUDIO_PROCESSING_NS_NOISE_SUPPRESSION_H_ 11 | #define WEBRTC_MODULES_AUDIO_PROCESSING_NS_NOISE_SUPPRESSION_H_ 12 | 13 | #include 14 | #include 15 | 16 | #define BLOCKL_MAX 160 // max processing block length: 160 17 | #define ANAL_BLOCKL_MAX 256 // max analysis block length: 256 18 | #define HALF_ANAL_BLOCKL 129 // half max analysis block length + 1 19 | #define NUM_HIGH_BANDS_MAX 2 // max number of high bands: 2 20 | 21 | #define QUANTILE (float)0.25 22 | 23 | #define SIMULT 3 24 | #define END_STARTUP_LONG 200 25 | #define END_STARTUP_SHORT 50 26 | #define FACTOR (float)40.0 27 | #define WIDTH (float)0.01 28 | 29 | // Length of fft work arrays. 30 | #define IP_LENGTH (ANAL_BLOCKL_MAX >> 1) // must be at least ceil(2 + sqrt(ANAL_BLOCKL_MAX/2)) 31 | #define W_LENGTH (ANAL_BLOCKL_MAX >> 1) 32 | 33 | //PARAMETERS FOR NEW METHOD 34 | #define DD_PR_SNR (float)0.98 // DD update of prior SNR 35 | #define LRT_TAVG (float)0.50 // tavg parameter for LRT (previously 0.90) 36 | #define SPECT_FL_TAVG (float)0.30 // tavg parameter for spectral flatness measure 37 | #define SPECT_DIFF_TAVG (float)0.30 // tavg parameter for spectral difference measure 38 | #define PRIOR_UPDATE (float)0.10 // update parameter of prior model 39 | #define NOISE_UPDATE (float)0.90 // update parameter for noise 40 | #define SPEECH_UPDATE (float)0.99 // update parameter when likely speech 41 | #define WIDTH_PR_MAP (float)4.0 // width parameter in sigmoid map for prior model 42 | #define LRT_FEATURE_THR (float)0.5 // default threshold for LRT feature 43 | #define SF_FEATURE_THR (float)0.5 // default threshold for Spectral Flatness feature 44 | #define PROB_RANGE (float)0.20 // probability threshold for noise state in 45 | // speech/noise likelihood 46 | #define HIST_PAR_EST 1000 // histogram size for estimation of parameters 47 | #define GAMMA_PAUSE (float)0.05 // update for conservative noise estimate 48 | // 49 | #define B_LIM (float)0.5 // threshold in final energy gain factor calculation 50 | 51 | 52 | #include 53 | 54 | 55 | typedef struct NsHandleT NsHandle; 56 | 57 | #ifdef __cplusplus 58 | extern "C" { 59 | #endif 60 | 61 | typedef struct NSParaExtract_ { 62 | // Bin size of histogram. 63 | float binSizeLrt; 64 | float binSizeSpecFlat; 65 | float binSizeSpecDiff; 66 | // Range of histogram over which LRT threshold is computed. 67 | float rangeAvgHistLrt; 68 | // Scale parameters: multiply dominant peaks of the histograms by scale factor 69 | // to obtain thresholds for prior model. 70 | float factor1ModelPars; // For LRT and spectral difference. 71 | float factor2ModelPars; // For spectral_flatness: used when noise is flatter 72 | // than speech. 73 | // Peak limit for spectral flatness (varies between 0 and 1). 74 | float thresPosSpecFlat; 75 | // Limit on spacing of two highest peaks in histogram: spacing determined by 76 | // bin size. 77 | float limitPeakSpacingSpecFlat; 78 | float limitPeakSpacingSpecDiff; 79 | // Limit on relevance of second peak. 80 | float limitPeakWeightsSpecFlat; 81 | float limitPeakWeightsSpecDiff; 82 | // Limit on fluctuation of LRT feature. 83 | float thresFluctLrt; 84 | // Limit on the max and min values for the feature thresholds. 85 | float maxLrt; 86 | float minLrt; 87 | float maxSpecFlat; 88 | float minSpecFlat; 89 | float maxSpecDiff; 90 | float minSpecDiff; 91 | // Criteria of weight of histogram peak to accept/reject feature. 92 | int thresWeightSpecFlat; 93 | int thresWeightSpecDiff; 94 | 95 | } NSParaExtract; 96 | 97 | typedef struct NoiseSuppressionC_ { 98 | uint32_t fs; 99 | size_t blockLen; 100 | size_t windShift; 101 | size_t anaLen; 102 | size_t magnLen; 103 | int aggrMode; 104 | const float *window; 105 | float analyzeBuf[ANAL_BLOCKL_MAX]; 106 | float dataBuf[ANAL_BLOCKL_MAX]; 107 | float syntBuf[ANAL_BLOCKL_MAX]; 108 | 109 | int initFlag; 110 | // Parameters for quantile noise estimation. 111 | float density[SIMULT * HALF_ANAL_BLOCKL]; 112 | float lquantile[SIMULT * HALF_ANAL_BLOCKL]; 113 | float quantile[HALF_ANAL_BLOCKL]; 114 | int counter[SIMULT]; 115 | int updates; 116 | // Parameters for Wiener filter. 117 | float smooth[HALF_ANAL_BLOCKL]; 118 | float overdrive; 119 | float denoiseBound; 120 | int gainmap; 121 | // FFT work arrays. 122 | size_t ip[IP_LENGTH]; 123 | float wfft[W_LENGTH]; 124 | 125 | // Parameters for new method: some not needed, will reduce/cleanup later. 126 | int32_t blockInd; // Frame index counter. 127 | int modelUpdatePars[4]; // Parameters for updating or estimating. 128 | // Thresholds/weights for prior model. 129 | float priorModelPars[7]; // Parameters for prior model. 130 | float noise[HALF_ANAL_BLOCKL]; // Noise spectrum from current frame. 131 | float noisePrev[HALF_ANAL_BLOCKL]; // Noise spectrum from previous frame. 132 | // Magnitude spectrum of previous analyze frame. 133 | float magnPrevAnalyze[HALF_ANAL_BLOCKL]; 134 | // Magnitude spectrum of previous process frame. 135 | float magnPrevProcess[HALF_ANAL_BLOCKL]; 136 | float logLrtTimeAvg[HALF_ANAL_BLOCKL]; // Log LRT factor with time-smoothing. 137 | float priorSpeechProb; // Prior speech/noise probability. 138 | float featureData[7]; 139 | // Conservative noise spectrum estimate. 140 | float magnAvgPause[HALF_ANAL_BLOCKL]; 141 | float signalEnergy; // Energy of |magn|. 142 | float sumMagn; 143 | float whiteNoiseLevel; // Initial noise estimate. 144 | float initMagnEst[HALF_ANAL_BLOCKL]; // Initial magnitude spectrum estimate. 145 | float pinkNoiseNumerator; // Pink noise parameter: numerator. 146 | float pinkNoiseExp; // Pink noise parameter: power of frequencies. 147 | float parametricNoise[HALF_ANAL_BLOCKL]; 148 | // Parameters for feature extraction. 149 | NSParaExtract featureExtractionParams; 150 | // Histograms for parameter estimation. 151 | int histLrt[HIST_PAR_EST]; 152 | int histSpecFlat[HIST_PAR_EST]; 153 | int histSpecDiff[HIST_PAR_EST]; 154 | // Quantities for high band estimate. 155 | float speechProb[HALF_ANAL_BLOCKL]; // Final speech/noise prob: prior + LRT. 156 | // Buffering data for HB. 157 | float dataBufHB[NUM_HIGH_BANDS_MAX][ANAL_BLOCKL_MAX]; 158 | 159 | } NoiseSuppressionC; 160 | 161 | // Refer to fft4g.c for documentation. 162 | void WebRtc_rdft(size_t n, int isgn, float *a, size_t *ip, float *w); 163 | 164 | /**************************************************************************** 165 | * WebRtcNs_InitCore(...) 166 | * 167 | * This function initializes a noise suppression instance 168 | * 169 | * Input: 170 | * - self : Instance that should be initialized 171 | * - fs : Sampling frequency 172 | * 173 | * Output: 174 | * - self : Initialized instance 175 | * 176 | * Return value : 0 - Ok 177 | * -1 - Error 178 | */ 179 | int WebRtcNs_InitCore(NoiseSuppressionC *self, uint32_t fs); 180 | 181 | /**************************************************************************** 182 | * WebRtcNs_set_policy_core(...) 183 | * 184 | * This changes the aggressiveness of the noise suppression method. 185 | * 186 | * Input: 187 | * - self : Instance that should be initialized 188 | * - mode : 0: Mild (6dB), 1: Medium (10dB), 2: Aggressive (15dB) 189 | * 190 | * Output: 191 | * - self : Initialized instance 192 | * 193 | * Return value : 0 - Ok 194 | * -1 - Error 195 | */ 196 | int WebRtcNs_set_policy_core(NoiseSuppressionC *self, int mode); 197 | 198 | /**************************************************************************** 199 | * WebRtcNs_AnalyzeCore 200 | * 201 | * Estimate the background noise. 202 | * 203 | * Input: 204 | * - self : Instance that should be initialized 205 | * - speechFrame : Input speech frame for lower band 206 | * 207 | * Output: 208 | * - self : Updated instance 209 | */ 210 | void WebRtcNs_AnalyzeCore(NoiseSuppressionC *self, const int16_t *speechFrame); 211 | 212 | /**************************************************************************** 213 | * WebRtcNs_ProcessCore 214 | * 215 | * Do noise suppression. 216 | * 217 | * Input: 218 | * - self : Instance that should be initialized 219 | * - inFrame : Input speech frame for each band 220 | * - num_bands : Number of bands 221 | * 222 | * Output: 223 | * - self : Updated instance 224 | * - outFrame : Output speech frame for each band 225 | */ 226 | void WebRtcNs_ProcessCore(NoiseSuppressionC *self, 227 | const int16_t *const *inFrame, 228 | size_t num_bands, 229 | int16_t *const *outFrame); 230 | 231 | /* 232 | * This function creates an instance of the floating point Noise Suppression. 233 | */ 234 | NsHandle *WebRtcNs_Create(); 235 | 236 | /* 237 | * This function frees the dynamic memory of a specified noise suppression 238 | * instance. 239 | * 240 | * Input: 241 | * - NS_inst : Pointer to NS instance that should be freed 242 | */ 243 | void WebRtcNs_Free(NsHandle *NS_inst); 244 | 245 | /* 246 | * This function initializes a NS instance and has to be called before any other 247 | * processing is made. 248 | * 249 | * Input: 250 | * - NS_inst : Instance that should be initialized 251 | * - fs : sampling frequency 252 | * 253 | * Output: 254 | * - NS_inst : Initialized instance 255 | * 256 | * Return value : 0 - Ok 257 | * -1 - Error 258 | */ 259 | int WebRtcNs_Init(NsHandle *NS_inst, uint32_t fs); 260 | 261 | /* 262 | * This changes the aggressiveness of the noise suppression method. 263 | * 264 | * Input: 265 | * - NS_inst : Noise suppression instance. 266 | * - mode : 0: Mild, 1: Medium , 2: Aggressive 267 | * 268 | * Output: 269 | * - NS_inst : Updated instance. 270 | * 271 | * Return value : 0 - Ok 272 | * -1 - Error 273 | */ 274 | int WebRtcNs_set_policy(NsHandle *NS_inst, int mode); 275 | 276 | /* 277 | * This functions estimates the background noise for the inserted speech frame. 278 | * The input and output signals should always be 10ms (80 or 160 samples). 279 | * 280 | * Input 281 | * - NS_inst : Noise suppression instance. 282 | * - spframe : Pointer to speech frame buffer for L band 283 | * 284 | * Output: 285 | * - NS_inst : Updated NS instance 286 | */ 287 | void WebRtcNs_Analyze(NsHandle *NS_inst, const int16_t *spframe); 288 | 289 | /* 290 | * This functions does Noise Suppression for the inserted speech frame. The 291 | * input and output signals should always be 10ms (80 or 160 samples). 292 | * 293 | * Input 294 | * - NS_inst : Noise suppression instance. 295 | * - spframe : Pointer to speech frame buffer for each band 296 | * - num_bands : Number of bands 297 | * 298 | * Output: 299 | * - NS_inst : Updated NS instance 300 | * - outframe : Pointer to output frame for each band 301 | */ 302 | void WebRtcNs_Process(NsHandle *NS_inst, 303 | const int16_t *const *spframe, 304 | size_t num_bands, 305 | int16_t *const *outframe); 306 | 307 | /* Returns the internally used prior speech probability of the current frame. 308 | * There is a frequency bin based one as well, with which this should not be 309 | * confused. 310 | * 311 | * Input 312 | * - handle : Noise suppression instance. 313 | * 314 | * Return value : Prior speech probability in interval [0.0, 1.0]. 315 | * -1 - NULL pointer or uninitialized instance. 316 | */ 317 | float WebRtcNs_prior_speech_probability(NsHandle *handle); 318 | 319 | /* Returns a pointer to the noise estimate per frequency bin. The number of 320 | * frequency bins can be provided using WebRtcNs_num_freq(). 321 | * 322 | * Input 323 | * - handle : Noise suppression instance. 324 | * 325 | * Return value : Pointer to the noise estimate per frequency bin. 326 | * Returns NULL if the input is a NULL pointer or an 327 | * uninitialized instance. 328 | */ 329 | const float *WebRtcNs_noise_estimate(const NsHandle *handle); 330 | 331 | /* Returns the number of frequency bins, which is the length of the noise 332 | * estimate for example. 333 | * 334 | * Return value : Number of frequency bins. 335 | */ 336 | size_t WebRtcNs_num_freq(); 337 | 338 | #ifdef __cplusplus 339 | } 340 | #endif 341 | 342 | #endif // WEBRTC_MODULES_AUDIO_PROCESSING_NS_NOISE_SUPPRESSION_H_ 343 | -------------------------------------------------------------------------------- /noiseReduction/noiseReduction.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 169F0CFA212EAE7000CB72AC /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 169F0CF9212EAE7000CB72AC /* AppDelegate.m */; }; 11 | 169F0CFD212EAE7000CB72AC /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 169F0CFC212EAE7000CB72AC /* ViewController.m */; }; 12 | 169F0D00212EAE7000CB72AC /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 169F0CFE212EAE7000CB72AC /* Main.storyboard */; }; 13 | 169F0D02212EAE7000CB72AC /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 169F0D01212EAE7000CB72AC /* Assets.xcassets */; }; 14 | 169F0D05212EAE7000CB72AC /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 169F0D03212EAE7000CB72AC /* LaunchScreen.storyboard */; }; 15 | 169F0D08212EAE7100CB72AC /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 169F0D07212EAE7100CB72AC /* main.m */; }; 16 | 169F0D12212EAE7100CB72AC /* noiseReductionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 169F0D11212EAE7100CB72AC /* noiseReductionTests.m */; }; 17 | 169F0D1D212EAE7100CB72AC /* noiseReductionUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 169F0D1C212EAE7100CB72AC /* noiseReductionUITests.m */; }; 18 | C1E15A39212ED64B00D366FC /* noise_suppression.c in Sources */ = {isa = PBXBuildFile; fileRef = C1E15A36212ED64A00D366FC /* noise_suppression.c */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXContainerItemProxy section */ 22 | 169F0D0E212EAE7100CB72AC /* PBXContainerItemProxy */ = { 23 | isa = PBXContainerItemProxy; 24 | containerPortal = 169F0CED212EAE7000CB72AC /* Project object */; 25 | proxyType = 1; 26 | remoteGlobalIDString = 169F0CF4212EAE7000CB72AC; 27 | remoteInfo = noiseReduction; 28 | }; 29 | 169F0D19212EAE7100CB72AC /* PBXContainerItemProxy */ = { 30 | isa = PBXContainerItemProxy; 31 | containerPortal = 169F0CED212EAE7000CB72AC /* Project object */; 32 | proxyType = 1; 33 | remoteGlobalIDString = 169F0CF4212EAE7000CB72AC; 34 | remoteInfo = noiseReduction; 35 | }; 36 | /* End PBXContainerItemProxy section */ 37 | 38 | /* Begin PBXFileReference section */ 39 | 169F0CF5212EAE7000CB72AC /* noiseReduction.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = noiseReduction.app; sourceTree = BUILT_PRODUCTS_DIR; }; 40 | 169F0CF8212EAE7000CB72AC /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 41 | 169F0CF9212EAE7000CB72AC /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 42 | 169F0CFB212EAE7000CB72AC /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 43 | 169F0CFC212EAE7000CB72AC /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 44 | 169F0CFF212EAE7000CB72AC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 45 | 169F0D01212EAE7000CB72AC /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 46 | 169F0D04212EAE7000CB72AC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 47 | 169F0D06212EAE7100CB72AC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 48 | 169F0D07212EAE7100CB72AC /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 49 | 169F0D0D212EAE7100CB72AC /* noiseReductionTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = noiseReductionTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 50 | 169F0D11212EAE7100CB72AC /* noiseReductionTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = noiseReductionTests.m; sourceTree = ""; }; 51 | 169F0D13212EAE7100CB72AC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 52 | 169F0D18212EAE7100CB72AC /* noiseReductionUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = noiseReductionUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 53 | 169F0D1C212EAE7100CB72AC /* noiseReductionUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = noiseReductionUITests.m; sourceTree = ""; }; 54 | 169F0D1E212EAE7100CB72AC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 55 | C1E15A35212ED64A00D366FC /* dr_wav.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dr_wav.h; sourceTree = ""; }; 56 | C1E15A36212ED64A00D366FC /* noise_suppression.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = noise_suppression.c; sourceTree = ""; }; 57 | C1E15A37212ED64B00D366FC /* noise_suppression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = noise_suppression.h; sourceTree = ""; }; 58 | C1E15A38212ED64B00D366FC /* timing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = timing.h; sourceTree = ""; }; 59 | /* End PBXFileReference section */ 60 | 61 | /* Begin PBXFrameworksBuildPhase section */ 62 | 169F0CF2212EAE7000CB72AC /* Frameworks */ = { 63 | isa = PBXFrameworksBuildPhase; 64 | buildActionMask = 2147483647; 65 | files = ( 66 | ); 67 | runOnlyForDeploymentPostprocessing = 0; 68 | }; 69 | 169F0D0A212EAE7100CB72AC /* Frameworks */ = { 70 | isa = PBXFrameworksBuildPhase; 71 | buildActionMask = 2147483647; 72 | files = ( 73 | ); 74 | runOnlyForDeploymentPostprocessing = 0; 75 | }; 76 | 169F0D15212EAE7100CB72AC /* Frameworks */ = { 77 | isa = PBXFrameworksBuildPhase; 78 | buildActionMask = 2147483647; 79 | files = ( 80 | ); 81 | runOnlyForDeploymentPostprocessing = 0; 82 | }; 83 | /* End PBXFrameworksBuildPhase section */ 84 | 85 | /* Begin PBXGroup section */ 86 | 169F0CEC212EAE7000CB72AC = { 87 | isa = PBXGroup; 88 | children = ( 89 | 169F0CF7212EAE7000CB72AC /* noiseReduction */, 90 | 169F0D10212EAE7100CB72AC /* noiseReductionTests */, 91 | 169F0D1B212EAE7100CB72AC /* noiseReductionUITests */, 92 | 169F0CF6212EAE7000CB72AC /* Products */, 93 | ); 94 | sourceTree = ""; 95 | }; 96 | 169F0CF6212EAE7000CB72AC /* Products */ = { 97 | isa = PBXGroup; 98 | children = ( 99 | 169F0CF5212EAE7000CB72AC /* noiseReduction.app */, 100 | 169F0D0D212EAE7100CB72AC /* noiseReductionTests.xctest */, 101 | 169F0D18212EAE7100CB72AC /* noiseReductionUITests.xctest */, 102 | ); 103 | name = Products; 104 | sourceTree = ""; 105 | }; 106 | 169F0CF7212EAE7000CB72AC /* noiseReduction */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | C1E15A3A212ED65000D366FC /* SDK */, 110 | 169F0CF8212EAE7000CB72AC /* AppDelegate.h */, 111 | 169F0CF9212EAE7000CB72AC /* AppDelegate.m */, 112 | 169F0CFB212EAE7000CB72AC /* ViewController.h */, 113 | 169F0CFC212EAE7000CB72AC /* ViewController.m */, 114 | 169F0CFE212EAE7000CB72AC /* Main.storyboard */, 115 | 169F0D01212EAE7000CB72AC /* Assets.xcassets */, 116 | 169F0D03212EAE7000CB72AC /* LaunchScreen.storyboard */, 117 | 169F0D06212EAE7100CB72AC /* Info.plist */, 118 | 169F0D07212EAE7100CB72AC /* main.m */, 119 | ); 120 | path = noiseReduction; 121 | sourceTree = ""; 122 | }; 123 | 169F0D10212EAE7100CB72AC /* noiseReductionTests */ = { 124 | isa = PBXGroup; 125 | children = ( 126 | 169F0D11212EAE7100CB72AC /* noiseReductionTests.m */, 127 | 169F0D13212EAE7100CB72AC /* Info.plist */, 128 | ); 129 | path = noiseReductionTests; 130 | sourceTree = ""; 131 | }; 132 | 169F0D1B212EAE7100CB72AC /* noiseReductionUITests */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | 169F0D1C212EAE7100CB72AC /* noiseReductionUITests.m */, 136 | 169F0D1E212EAE7100CB72AC /* Info.plist */, 137 | ); 138 | path = noiseReductionUITests; 139 | sourceTree = ""; 140 | }; 141 | C1E15A3A212ED65000D366FC /* SDK */ = { 142 | isa = PBXGroup; 143 | children = ( 144 | C1E15A35212ED64A00D366FC /* dr_wav.h */, 145 | C1E15A38212ED64B00D366FC /* timing.h */, 146 | C1E15A37212ED64B00D366FC /* noise_suppression.h */, 147 | C1E15A36212ED64A00D366FC /* noise_suppression.c */, 148 | ); 149 | path = SDK; 150 | sourceTree = ""; 151 | }; 152 | /* End PBXGroup section */ 153 | 154 | /* Begin PBXNativeTarget section */ 155 | 169F0CF4212EAE7000CB72AC /* noiseReduction */ = { 156 | isa = PBXNativeTarget; 157 | buildConfigurationList = 169F0D21212EAE7100CB72AC /* Build configuration list for PBXNativeTarget "noiseReduction" */; 158 | buildPhases = ( 159 | 169F0CF1212EAE7000CB72AC /* Sources */, 160 | 169F0CF2212EAE7000CB72AC /* Frameworks */, 161 | 169F0CF3212EAE7000CB72AC /* Resources */, 162 | ); 163 | buildRules = ( 164 | ); 165 | dependencies = ( 166 | ); 167 | name = noiseReduction; 168 | productName = noiseReduction; 169 | productReference = 169F0CF5212EAE7000CB72AC /* noiseReduction.app */; 170 | productType = "com.apple.product-type.application"; 171 | }; 172 | 169F0D0C212EAE7100CB72AC /* noiseReductionTests */ = { 173 | isa = PBXNativeTarget; 174 | buildConfigurationList = 169F0D24212EAE7100CB72AC /* Build configuration list for PBXNativeTarget "noiseReductionTests" */; 175 | buildPhases = ( 176 | 169F0D09212EAE7100CB72AC /* Sources */, 177 | 169F0D0A212EAE7100CB72AC /* Frameworks */, 178 | 169F0D0B212EAE7100CB72AC /* Resources */, 179 | ); 180 | buildRules = ( 181 | ); 182 | dependencies = ( 183 | 169F0D0F212EAE7100CB72AC /* PBXTargetDependency */, 184 | ); 185 | name = noiseReductionTests; 186 | productName = noiseReductionTests; 187 | productReference = 169F0D0D212EAE7100CB72AC /* noiseReductionTests.xctest */; 188 | productType = "com.apple.product-type.bundle.unit-test"; 189 | }; 190 | 169F0D17212EAE7100CB72AC /* noiseReductionUITests */ = { 191 | isa = PBXNativeTarget; 192 | buildConfigurationList = 169F0D27212EAE7100CB72AC /* Build configuration list for PBXNativeTarget "noiseReductionUITests" */; 193 | buildPhases = ( 194 | 169F0D14212EAE7100CB72AC /* Sources */, 195 | 169F0D15212EAE7100CB72AC /* Frameworks */, 196 | 169F0D16212EAE7100CB72AC /* Resources */, 197 | ); 198 | buildRules = ( 199 | ); 200 | dependencies = ( 201 | 169F0D1A212EAE7100CB72AC /* PBXTargetDependency */, 202 | ); 203 | name = noiseReductionUITests; 204 | productName = noiseReductionUITests; 205 | productReference = 169F0D18212EAE7100CB72AC /* noiseReductionUITests.xctest */; 206 | productType = "com.apple.product-type.bundle.ui-testing"; 207 | }; 208 | /* End PBXNativeTarget section */ 209 | 210 | /* Begin PBXProject section */ 211 | 169F0CED212EAE7000CB72AC /* Project object */ = { 212 | isa = PBXProject; 213 | attributes = { 214 | LastUpgradeCheck = 0920; 215 | ORGANIZATIONNAME = LJP; 216 | TargetAttributes = { 217 | 169F0CF4212EAE7000CB72AC = { 218 | CreatedOnToolsVersion = 9.2; 219 | ProvisioningStyle = Automatic; 220 | }; 221 | 169F0D0C212EAE7100CB72AC = { 222 | CreatedOnToolsVersion = 9.2; 223 | ProvisioningStyle = Automatic; 224 | TestTargetID = 169F0CF4212EAE7000CB72AC; 225 | }; 226 | 169F0D17212EAE7100CB72AC = { 227 | CreatedOnToolsVersion = 9.2; 228 | ProvisioningStyle = Automatic; 229 | TestTargetID = 169F0CF4212EAE7000CB72AC; 230 | }; 231 | }; 232 | }; 233 | buildConfigurationList = 169F0CF0212EAE7000CB72AC /* Build configuration list for PBXProject "noiseReduction" */; 234 | compatibilityVersion = "Xcode 8.0"; 235 | developmentRegion = en; 236 | hasScannedForEncodings = 0; 237 | knownRegions = ( 238 | en, 239 | Base, 240 | ); 241 | mainGroup = 169F0CEC212EAE7000CB72AC; 242 | productRefGroup = 169F0CF6212EAE7000CB72AC /* Products */; 243 | projectDirPath = ""; 244 | projectRoot = ""; 245 | targets = ( 246 | 169F0CF4212EAE7000CB72AC /* noiseReduction */, 247 | 169F0D0C212EAE7100CB72AC /* noiseReductionTests */, 248 | 169F0D17212EAE7100CB72AC /* noiseReductionUITests */, 249 | ); 250 | }; 251 | /* End PBXProject section */ 252 | 253 | /* Begin PBXResourcesBuildPhase section */ 254 | 169F0CF3212EAE7000CB72AC /* Resources */ = { 255 | isa = PBXResourcesBuildPhase; 256 | buildActionMask = 2147483647; 257 | files = ( 258 | 169F0D05212EAE7000CB72AC /* LaunchScreen.storyboard in Resources */, 259 | 169F0D02212EAE7000CB72AC /* Assets.xcassets in Resources */, 260 | 169F0D00212EAE7000CB72AC /* Main.storyboard in Resources */, 261 | ); 262 | runOnlyForDeploymentPostprocessing = 0; 263 | }; 264 | 169F0D0B212EAE7100CB72AC /* Resources */ = { 265 | isa = PBXResourcesBuildPhase; 266 | buildActionMask = 2147483647; 267 | files = ( 268 | ); 269 | runOnlyForDeploymentPostprocessing = 0; 270 | }; 271 | 169F0D16212EAE7100CB72AC /* Resources */ = { 272 | isa = PBXResourcesBuildPhase; 273 | buildActionMask = 2147483647; 274 | files = ( 275 | ); 276 | runOnlyForDeploymentPostprocessing = 0; 277 | }; 278 | /* End PBXResourcesBuildPhase section */ 279 | 280 | /* Begin PBXSourcesBuildPhase section */ 281 | 169F0CF1212EAE7000CB72AC /* Sources */ = { 282 | isa = PBXSourcesBuildPhase; 283 | buildActionMask = 2147483647; 284 | files = ( 285 | C1E15A39212ED64B00D366FC /* noise_suppression.c in Sources */, 286 | 169F0CFD212EAE7000CB72AC /* ViewController.m in Sources */, 287 | 169F0D08212EAE7100CB72AC /* main.m in Sources */, 288 | 169F0CFA212EAE7000CB72AC /* AppDelegate.m in Sources */, 289 | ); 290 | runOnlyForDeploymentPostprocessing = 0; 291 | }; 292 | 169F0D09212EAE7100CB72AC /* Sources */ = { 293 | isa = PBXSourcesBuildPhase; 294 | buildActionMask = 2147483647; 295 | files = ( 296 | 169F0D12212EAE7100CB72AC /* noiseReductionTests.m in Sources */, 297 | ); 298 | runOnlyForDeploymentPostprocessing = 0; 299 | }; 300 | 169F0D14212EAE7100CB72AC /* Sources */ = { 301 | isa = PBXSourcesBuildPhase; 302 | buildActionMask = 2147483647; 303 | files = ( 304 | 169F0D1D212EAE7100CB72AC /* noiseReductionUITests.m in Sources */, 305 | ); 306 | runOnlyForDeploymentPostprocessing = 0; 307 | }; 308 | /* End PBXSourcesBuildPhase section */ 309 | 310 | /* Begin PBXTargetDependency section */ 311 | 169F0D0F212EAE7100CB72AC /* PBXTargetDependency */ = { 312 | isa = PBXTargetDependency; 313 | target = 169F0CF4212EAE7000CB72AC /* noiseReduction */; 314 | targetProxy = 169F0D0E212EAE7100CB72AC /* PBXContainerItemProxy */; 315 | }; 316 | 169F0D1A212EAE7100CB72AC /* PBXTargetDependency */ = { 317 | isa = PBXTargetDependency; 318 | target = 169F0CF4212EAE7000CB72AC /* noiseReduction */; 319 | targetProxy = 169F0D19212EAE7100CB72AC /* PBXContainerItemProxy */; 320 | }; 321 | /* End PBXTargetDependency section */ 322 | 323 | /* Begin PBXVariantGroup section */ 324 | 169F0CFE212EAE7000CB72AC /* Main.storyboard */ = { 325 | isa = PBXVariantGroup; 326 | children = ( 327 | 169F0CFF212EAE7000CB72AC /* Base */, 328 | ); 329 | name = Main.storyboard; 330 | sourceTree = ""; 331 | }; 332 | 169F0D03212EAE7000CB72AC /* LaunchScreen.storyboard */ = { 333 | isa = PBXVariantGroup; 334 | children = ( 335 | 169F0D04212EAE7000CB72AC /* Base */, 336 | ); 337 | name = LaunchScreen.storyboard; 338 | sourceTree = ""; 339 | }; 340 | /* End PBXVariantGroup section */ 341 | 342 | /* Begin XCBuildConfiguration section */ 343 | 169F0D1F212EAE7100CB72AC /* Debug */ = { 344 | isa = XCBuildConfiguration; 345 | buildSettings = { 346 | ALWAYS_SEARCH_USER_PATHS = NO; 347 | CLANG_ANALYZER_NONNULL = YES; 348 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 349 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 350 | CLANG_CXX_LIBRARY = "libc++"; 351 | CLANG_ENABLE_MODULES = YES; 352 | CLANG_ENABLE_OBJC_ARC = YES; 353 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 354 | CLANG_WARN_BOOL_CONVERSION = YES; 355 | CLANG_WARN_COMMA = YES; 356 | CLANG_WARN_CONSTANT_CONVERSION = YES; 357 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 358 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 359 | CLANG_WARN_EMPTY_BODY = YES; 360 | CLANG_WARN_ENUM_CONVERSION = YES; 361 | CLANG_WARN_INFINITE_RECURSION = YES; 362 | CLANG_WARN_INT_CONVERSION = YES; 363 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 364 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 365 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 366 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 367 | CLANG_WARN_STRICT_PROTOTYPES = YES; 368 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 369 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 370 | CLANG_WARN_UNREACHABLE_CODE = YES; 371 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 372 | CODE_SIGN_IDENTITY = "iPhone Developer"; 373 | COPY_PHASE_STRIP = NO; 374 | DEBUG_INFORMATION_FORMAT = dwarf; 375 | ENABLE_STRICT_OBJC_MSGSEND = YES; 376 | ENABLE_TESTABILITY = YES; 377 | GCC_C_LANGUAGE_STANDARD = gnu11; 378 | GCC_DYNAMIC_NO_PIC = NO; 379 | GCC_NO_COMMON_BLOCKS = YES; 380 | GCC_OPTIMIZATION_LEVEL = 0; 381 | GCC_PREPROCESSOR_DEFINITIONS = ( 382 | "DEBUG=1", 383 | "$(inherited)", 384 | ); 385 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 386 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 387 | GCC_WARN_UNDECLARED_SELECTOR = YES; 388 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 389 | GCC_WARN_UNUSED_FUNCTION = YES; 390 | GCC_WARN_UNUSED_VARIABLE = YES; 391 | IPHONEOS_DEPLOYMENT_TARGET = 11.2; 392 | MTL_ENABLE_DEBUG_INFO = YES; 393 | ONLY_ACTIVE_ARCH = YES; 394 | SDKROOT = iphoneos; 395 | }; 396 | name = Debug; 397 | }; 398 | 169F0D20212EAE7100CB72AC /* Release */ = { 399 | isa = XCBuildConfiguration; 400 | buildSettings = { 401 | ALWAYS_SEARCH_USER_PATHS = NO; 402 | CLANG_ANALYZER_NONNULL = YES; 403 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 404 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 405 | CLANG_CXX_LIBRARY = "libc++"; 406 | CLANG_ENABLE_MODULES = YES; 407 | CLANG_ENABLE_OBJC_ARC = YES; 408 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 409 | CLANG_WARN_BOOL_CONVERSION = YES; 410 | CLANG_WARN_COMMA = YES; 411 | CLANG_WARN_CONSTANT_CONVERSION = YES; 412 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 413 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 414 | CLANG_WARN_EMPTY_BODY = YES; 415 | CLANG_WARN_ENUM_CONVERSION = YES; 416 | CLANG_WARN_INFINITE_RECURSION = YES; 417 | CLANG_WARN_INT_CONVERSION = YES; 418 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 419 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 420 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 421 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 422 | CLANG_WARN_STRICT_PROTOTYPES = YES; 423 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 424 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 425 | CLANG_WARN_UNREACHABLE_CODE = YES; 426 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 427 | CODE_SIGN_IDENTITY = "iPhone Developer"; 428 | COPY_PHASE_STRIP = NO; 429 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 430 | ENABLE_NS_ASSERTIONS = NO; 431 | ENABLE_STRICT_OBJC_MSGSEND = YES; 432 | GCC_C_LANGUAGE_STANDARD = gnu11; 433 | GCC_NO_COMMON_BLOCKS = YES; 434 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 435 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 436 | GCC_WARN_UNDECLARED_SELECTOR = YES; 437 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 438 | GCC_WARN_UNUSED_FUNCTION = YES; 439 | GCC_WARN_UNUSED_VARIABLE = YES; 440 | IPHONEOS_DEPLOYMENT_TARGET = 11.2; 441 | MTL_ENABLE_DEBUG_INFO = NO; 442 | SDKROOT = iphoneos; 443 | VALIDATE_PRODUCT = YES; 444 | }; 445 | name = Release; 446 | }; 447 | 169F0D22212EAE7100CB72AC /* Debug */ = { 448 | isa = XCBuildConfiguration; 449 | buildSettings = { 450 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 451 | CODE_SIGN_STYLE = Automatic; 452 | DEVELOPMENT_TEAM = G583SJY324; 453 | INFOPLIST_FILE = noiseReduction/Info.plist; 454 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 455 | PRODUCT_BUNDLE_IDENTIFIER = "-------------.noiseReduction"; 456 | PRODUCT_NAME = "$(TARGET_NAME)"; 457 | TARGETED_DEVICE_FAMILY = "1,2"; 458 | }; 459 | name = Debug; 460 | }; 461 | 169F0D23212EAE7100CB72AC /* Release */ = { 462 | isa = XCBuildConfiguration; 463 | buildSettings = { 464 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 465 | CODE_SIGN_STYLE = Automatic; 466 | DEVELOPMENT_TEAM = G583SJY324; 467 | INFOPLIST_FILE = noiseReduction/Info.plist; 468 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 469 | PRODUCT_BUNDLE_IDENTIFIER = "-------------.noiseReduction"; 470 | PRODUCT_NAME = "$(TARGET_NAME)"; 471 | TARGETED_DEVICE_FAMILY = "1,2"; 472 | }; 473 | name = Release; 474 | }; 475 | 169F0D25212EAE7100CB72AC /* Debug */ = { 476 | isa = XCBuildConfiguration; 477 | buildSettings = { 478 | BUNDLE_LOADER = "$(TEST_HOST)"; 479 | CODE_SIGN_STYLE = Automatic; 480 | INFOPLIST_FILE = noiseReductionTests/Info.plist; 481 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 482 | PRODUCT_BUNDLE_IDENTIFIER = "-------------.noiseReductionTests"; 483 | PRODUCT_NAME = "$(TARGET_NAME)"; 484 | TARGETED_DEVICE_FAMILY = "1,2"; 485 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/noiseReduction.app/noiseReduction"; 486 | }; 487 | name = Debug; 488 | }; 489 | 169F0D26212EAE7100CB72AC /* Release */ = { 490 | isa = XCBuildConfiguration; 491 | buildSettings = { 492 | BUNDLE_LOADER = "$(TEST_HOST)"; 493 | CODE_SIGN_STYLE = Automatic; 494 | INFOPLIST_FILE = noiseReductionTests/Info.plist; 495 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 496 | PRODUCT_BUNDLE_IDENTIFIER = "-------------.noiseReductionTests"; 497 | PRODUCT_NAME = "$(TARGET_NAME)"; 498 | TARGETED_DEVICE_FAMILY = "1,2"; 499 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/noiseReduction.app/noiseReduction"; 500 | }; 501 | name = Release; 502 | }; 503 | 169F0D28212EAE7100CB72AC /* Debug */ = { 504 | isa = XCBuildConfiguration; 505 | buildSettings = { 506 | CODE_SIGN_STYLE = Automatic; 507 | INFOPLIST_FILE = noiseReductionUITests/Info.plist; 508 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 509 | PRODUCT_BUNDLE_IDENTIFIER = "-------------.noiseReductionUITests"; 510 | PRODUCT_NAME = "$(TARGET_NAME)"; 511 | TARGETED_DEVICE_FAMILY = "1,2"; 512 | TEST_TARGET_NAME = noiseReduction; 513 | }; 514 | name = Debug; 515 | }; 516 | 169F0D29212EAE7100CB72AC /* Release */ = { 517 | isa = XCBuildConfiguration; 518 | buildSettings = { 519 | CODE_SIGN_STYLE = Automatic; 520 | INFOPLIST_FILE = noiseReductionUITests/Info.plist; 521 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 522 | PRODUCT_BUNDLE_IDENTIFIER = "-------------.noiseReductionUITests"; 523 | PRODUCT_NAME = "$(TARGET_NAME)"; 524 | TARGETED_DEVICE_FAMILY = "1,2"; 525 | TEST_TARGET_NAME = noiseReduction; 526 | }; 527 | name = Release; 528 | }; 529 | /* End XCBuildConfiguration section */ 530 | 531 | /* Begin XCConfigurationList section */ 532 | 169F0CF0212EAE7000CB72AC /* Build configuration list for PBXProject "noiseReduction" */ = { 533 | isa = XCConfigurationList; 534 | buildConfigurations = ( 535 | 169F0D1F212EAE7100CB72AC /* Debug */, 536 | 169F0D20212EAE7100CB72AC /* Release */, 537 | ); 538 | defaultConfigurationIsVisible = 0; 539 | defaultConfigurationName = Release; 540 | }; 541 | 169F0D21212EAE7100CB72AC /* Build configuration list for PBXNativeTarget "noiseReduction" */ = { 542 | isa = XCConfigurationList; 543 | buildConfigurations = ( 544 | 169F0D22212EAE7100CB72AC /* Debug */, 545 | 169F0D23212EAE7100CB72AC /* Release */, 546 | ); 547 | defaultConfigurationIsVisible = 0; 548 | defaultConfigurationName = Release; 549 | }; 550 | 169F0D24212EAE7100CB72AC /* Build configuration list for PBXNativeTarget "noiseReductionTests" */ = { 551 | isa = XCConfigurationList; 552 | buildConfigurations = ( 553 | 169F0D25212EAE7100CB72AC /* Debug */, 554 | 169F0D26212EAE7100CB72AC /* Release */, 555 | ); 556 | defaultConfigurationIsVisible = 0; 557 | defaultConfigurationName = Release; 558 | }; 559 | 169F0D27212EAE7100CB72AC /* Build configuration list for PBXNativeTarget "noiseReductionUITests" */ = { 560 | isa = XCConfigurationList; 561 | buildConfigurations = ( 562 | 169F0D28212EAE7100CB72AC /* Debug */, 563 | 169F0D29212EAE7100CB72AC /* Release */, 564 | ); 565 | defaultConfigurationIsVisible = 0; 566 | defaultConfigurationName = Release; 567 | }; 568 | /* End XCConfigurationList section */ 569 | }; 570 | rootObject = 169F0CED212EAE7000CB72AC /* Project object */; 571 | } 572 | -------------------------------------------------------------------------------- /noiseReduction/noiseReduction/SDK/noise_suppression.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #include "noise_suppression.h" 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #ifndef SPL_SAT 18 | #define SPL_SAT(a, b, c) ((b) > (a) ? (a) : (b) < (c) ? (c) : (b)) 19 | #endif 20 | 21 | // hybrib Hanning & flat window 22 | static const float kBlocks80w128[128] = { 23 | (float) 0.00000000, (float) 0.03271908, (float) 0.06540313, (float) 0.09801714, (float) 0.13052619, 24 | (float) 0.16289547, (float) 0.19509032, (float) 0.22707626, (float) 0.25881905, (float) 0.29028468, 25 | (float) 0.32143947, (float) 0.35225005, (float) 0.38268343, (float) 0.41270703, (float) 0.44228869, 26 | (float) 0.47139674, (float) 0.50000000, (float) 0.52806785, (float) 0.55557023, (float) 0.58247770, 27 | (float) 0.60876143, (float) 0.63439328, (float) 0.65934582, (float) 0.68359230, (float) 0.70710678, 28 | (float) 0.72986407, (float) 0.75183981, (float) 0.77301045, (float) 0.79335334, (float) 0.81284668, 29 | (float) 0.83146961, (float) 0.84920218, (float) 0.86602540, (float) 0.88192126, (float) 0.89687274, 30 | (float) 0.91086382, (float) 0.92387953, (float) 0.93590593, (float) 0.94693013, (float) 0.95694034, 31 | (float) 0.96592583, (float) 0.97387698, (float) 0.98078528, (float) 0.98664333, (float) 0.99144486, 32 | (float) 0.99518473, (float) 0.99785892, (float) 0.99946459, (float) 1.00000000, (float) 1.00000000, 33 | (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, 34 | (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, 35 | (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, 36 | (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, 37 | (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, 38 | (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, 39 | (float) 1.00000000, (float) 0.99946459, (float) 0.99785892, (float) 0.99518473, (float) 0.99144486, 40 | (float) 0.98664333, (float) 0.98078528, (float) 0.97387698, (float) 0.96592583, (float) 0.95694034, 41 | (float) 0.94693013, (float) 0.93590593, (float) 0.92387953, (float) 0.91086382, (float) 0.89687274, 42 | (float) 0.88192126, (float) 0.86602540, (float) 0.84920218, (float) 0.83146961, (float) 0.81284668, 43 | (float) 0.79335334, (float) 0.77301045, (float) 0.75183981, (float) 0.72986407, (float) 0.70710678, 44 | (float) 0.68359230, (float) 0.65934582, (float) 0.63439328, (float) 0.60876143, (float) 0.58247770, 45 | (float) 0.55557023, (float) 0.52806785, (float) 0.50000000, (float) 0.47139674, (float) 0.44228869, 46 | (float) 0.41270703, (float) 0.38268343, (float) 0.35225005, (float) 0.32143947, (float) 0.29028468, 47 | (float) 0.25881905, (float) 0.22707626, (float) 0.19509032, (float) 0.16289547, (float) 0.13052619, 48 | (float) 0.09801714, (float) 0.06540313, (float) 0.03271908 49 | }; 50 | 51 | // hybrib Hanning & flat window 52 | static const float kBlocks160w256[256] = { 53 | (float) 0.00000000, (float) 0.01636173, (float) 0.03271908, (float) 0.04906767, (float) 0.06540313, 54 | (float) 0.08172107, (float) 0.09801714, (float) 0.11428696, (float) 0.13052619, (float) 0.14673047, 55 | (float) 0.16289547, (float) 0.17901686, (float) 0.19509032, (float) 0.21111155, (float) 0.22707626, 56 | (float) 0.24298018, (float) 0.25881905, (float) 0.27458862, (float) 0.29028468, (float) 0.30590302, 57 | (float) 0.32143947, (float) 0.33688985, (float) 0.35225005, (float) 0.36751594, (float) 0.38268343, 58 | (float) 0.39774847, (float) 0.41270703, (float) 0.42755509, (float) 0.44228869, (float) 0.45690388, 59 | (float) 0.47139674, (float) 0.48576339, (float) 0.50000000, (float) 0.51410274, (float) 0.52806785, 60 | (float) 0.54189158, (float) 0.55557023, (float) 0.56910015, (float) 0.58247770, (float) 0.59569930, 61 | (float) 0.60876143, (float) 0.62166057, (float) 0.63439328, (float) 0.64695615, (float) 0.65934582, 62 | (float) 0.67155895, (float) 0.68359230, (float) 0.69544264, (float) 0.70710678, (float) 0.71858162, 63 | (float) 0.72986407, (float) 0.74095113, (float) 0.75183981, (float) 0.76252720, (float) 0.77301045, 64 | (float) 0.78328675, (float) 0.79335334, (float) 0.80320753, (float) 0.81284668, (float) 0.82226822, 65 | (float) 0.83146961, (float) 0.84044840, (float) 0.84920218, (float) 0.85772861, (float) 0.86602540, 66 | (float) 0.87409034, (float) 0.88192126, (float) 0.88951608, (float) 0.89687274, (float) 0.90398929, 67 | (float) 0.91086382, (float) 0.91749450, (float) 0.92387953, (float) 0.93001722, (float) 0.93590593, 68 | (float) 0.94154407, (float) 0.94693013, (float) 0.95206268, (float) 0.95694034, (float) 0.96156180, 69 | (float) 0.96592583, (float) 0.97003125, (float) 0.97387698, (float) 0.97746197, (float) 0.98078528, 70 | (float) 0.98384601, (float) 0.98664333, (float) 0.98917651, (float) 0.99144486, (float) 0.99344778, 71 | (float) 0.99518473, (float) 0.99665524, (float) 0.99785892, (float) 0.99879546, (float) 0.99946459, 72 | (float) 0.99986614, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, 73 | (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, 74 | (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, 75 | (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, 76 | (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, 77 | (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, 78 | (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, 79 | (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, 80 | (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, 81 | (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, 82 | (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, 83 | (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, 84 | (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, (float) 1.00000000, 85 | (float) 1.00000000, (float) 0.99986614, (float) 0.99946459, (float) 0.99879546, (float) 0.99785892, 86 | (float) 0.99665524, (float) 0.99518473, (float) 0.99344778, (float) 0.99144486, (float) 0.98917651, 87 | (float) 0.98664333, (float) 0.98384601, (float) 0.98078528, (float) 0.97746197, (float) 0.97387698, 88 | (float) 0.97003125, (float) 0.96592583, (float) 0.96156180, (float) 0.95694034, (float) 0.95206268, 89 | (float) 0.94693013, (float) 0.94154407, (float) 0.93590593, (float) 0.93001722, (float) 0.92387953, 90 | (float) 0.91749450, (float) 0.91086382, (float) 0.90398929, (float) 0.89687274, (float) 0.88951608, 91 | (float) 0.88192126, (float) 0.87409034, (float) 0.86602540, (float) 0.85772861, (float) 0.84920218, 92 | (float) 0.84044840, (float) 0.83146961, (float) 0.82226822, (float) 0.81284668, (float) 0.80320753, 93 | (float) 0.79335334, (float) 0.78328675, (float) 0.77301045, (float) 0.76252720, (float) 0.75183981, 94 | (float) 0.74095113, (float) 0.72986407, (float) 0.71858162, (float) 0.70710678, (float) 0.69544264, 95 | (float) 0.68359230, (float) 0.67155895, (float) 0.65934582, (float) 0.64695615, (float) 0.63439328, 96 | (float) 0.62166057, (float) 0.60876143, (float) 0.59569930, (float) 0.58247770, (float) 0.56910015, 97 | (float) 0.55557023, (float) 0.54189158, (float) 0.52806785, (float) 0.51410274, (float) 0.50000000, 98 | (float) 0.48576339, (float) 0.47139674, (float) 0.45690388, (float) 0.44228869, (float) 0.42755509, 99 | (float) 0.41270703, (float) 0.39774847, (float) 0.38268343, (float) 0.36751594, (float) 0.35225005, 100 | (float) 0.33688985, (float) 0.32143947, (float) 0.30590302, (float) 0.29028468, (float) 0.27458862, 101 | (float) 0.25881905, (float) 0.24298018, (float) 0.22707626, (float) 0.21111155, (float) 0.19509032, 102 | (float) 0.17901686, (float) 0.16289547, (float) 0.14673047, (float) 0.13052619, (float) 0.11428696, 103 | (float) 0.09801714, (float) 0.08172107, (float) 0.06540313, (float) 0.04906767, (float) 0.03271908, 104 | (float) 0.01636173 105 | }; 106 | 107 | /* 108 | * http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html 109 | * Copyright Takuya OOURA, 1996-2001 110 | * 111 | * You may use, copy, modify and distribute this code for any purpose (include 112 | * commercial use) and without fee. Please refer to this package when you modify 113 | * this code. 114 | * 115 | * Changes: 116 | * Trivial type modifications by the WebRTC authors. 117 | */ 118 | 119 | static void makewt(size_t nw, size_t *ip, float *w); 120 | 121 | static void makect(size_t nc, size_t *ip, float *c); 122 | 123 | static void bitrv2(size_t n, size_t *ip, float *a); 124 | 125 | static void cftfsub(size_t n, float *a, float *w); 126 | 127 | static void cftbsub(size_t n, float *a, float *w); 128 | 129 | static void cft1st(size_t n, float *a, float *w); 130 | 131 | static void cftmdl(size_t n, size_t l, float *a, float *w); 132 | 133 | static void rftfsub(size_t n, float *a, size_t nc, float *c); 134 | 135 | static void rftbsub(size_t n, float *a, size_t nc, float *c); 136 | 137 | 138 | void WebRtc_rdft(size_t n, int isgn, float *a, size_t *ip, float *w) { 139 | size_t nw, nc; 140 | float xi; 141 | 142 | nw = ip[0]; 143 | if (n > (nw << 2)) { 144 | nw = n >> 2; 145 | makewt(nw, ip, w); 146 | } 147 | nc = ip[1]; 148 | if (n > (nc << 2)) { 149 | nc = n >> 2; 150 | makect(nc, ip, w + nw); 151 | } 152 | if (isgn >= 0) { 153 | if (n > 4) { 154 | bitrv2(n, ip + 2, a); 155 | cftfsub(n, a, w); 156 | rftfsub(n, a, nc, w + nw); 157 | } else if (n == 4) { 158 | cftfsub(n, a, w); 159 | } 160 | xi = a[0] - a[1]; 161 | a[0] += a[1]; 162 | a[1] = xi; 163 | } else { 164 | a[1] = 0.5f * (a[0] - a[1]); 165 | a[0] -= a[1]; 166 | if (n > 4) { 167 | rftbsub(n, a, nc, w + nw); 168 | bitrv2(n, ip + 2, a); 169 | cftbsub(n, a, w); 170 | } else if (n == 4) { 171 | cftfsub(n, a, w); 172 | } 173 | } 174 | } 175 | 176 | /* -------- initializing routines -------- */ 177 | 178 | 179 | 180 | static void makewt(size_t nw, size_t *ip, float *w) { 181 | size_t j, nwh; 182 | float delta, x, y; 183 | 184 | ip[0] = nw; 185 | ip[1] = 1; 186 | if (nw > 2) { 187 | nwh = nw >> 1; 188 | delta = atanf(1.0f) / nwh; 189 | w[0] = 1; 190 | w[1] = 0; 191 | w[nwh] = cosf(delta * nwh); 192 | w[nwh + 1] = w[nwh]; 193 | if (nwh > 2) { 194 | for (j = 2; j < nwh; j += 2) { 195 | x = cosf(delta * j); 196 | y = sinf(delta * j); 197 | w[j] = x; 198 | w[j + 1] = y; 199 | w[nw - j] = y; 200 | w[nw - j + 1] = x; 201 | } 202 | bitrv2(nw, ip + 2, w); 203 | } 204 | } 205 | } 206 | 207 | 208 | static void makect(size_t nc, size_t *ip, float *c) { 209 | size_t j, nch; 210 | float delta; 211 | 212 | ip[1] = nc; 213 | if (nc > 1) { 214 | nch = nc >> 1; 215 | delta = atanf(1.0f) / nch; 216 | c[0] = cosf(delta * nch); 217 | c[nch] = 0.5f * c[0]; 218 | for (j = 1; j < nch; j++) { 219 | c[j] = 0.5f * cosf(delta * j); 220 | c[nc - j] = 0.5f * sinf(delta * j); 221 | } 222 | } 223 | } 224 | 225 | 226 | /* -------- child routines -------- */ 227 | 228 | 229 | static void bitrv2(size_t n, size_t *ip, float *a) { 230 | size_t j, j1, k, k1, l, m, m2; 231 | float xr, xi, yr, yi; 232 | 233 | ip[0] = 0; 234 | l = n; 235 | m = 1; 236 | while ((m << 3) < l) { 237 | l >>= 1; 238 | for (j = 0; j < m; j++) { 239 | ip[m + j] = ip[j] + l; 240 | } 241 | m <<= 1; 242 | } 243 | m2 = 2 * m; 244 | if ((m << 3) == l) { 245 | for (k = 0; k < m; k++) { 246 | for (j = 0; j < k; j++) { 247 | j1 = 2 * j + ip[k]; 248 | k1 = 2 * k + ip[j]; 249 | xr = a[j1]; 250 | xi = a[j1 + 1]; 251 | yr = a[k1]; 252 | yi = a[k1 + 1]; 253 | a[j1] = yr; 254 | a[j1 + 1] = yi; 255 | a[k1] = xr; 256 | a[k1 + 1] = xi; 257 | j1 += m2; 258 | k1 += 2 * m2; 259 | xr = a[j1]; 260 | xi = a[j1 + 1]; 261 | yr = a[k1]; 262 | yi = a[k1 + 1]; 263 | a[j1] = yr; 264 | a[j1 + 1] = yi; 265 | a[k1] = xr; 266 | a[k1 + 1] = xi; 267 | j1 += m2; 268 | k1 -= m2; 269 | xr = a[j1]; 270 | xi = a[j1 + 1]; 271 | yr = a[k1]; 272 | yi = a[k1 + 1]; 273 | a[j1] = yr; 274 | a[j1 + 1] = yi; 275 | a[k1] = xr; 276 | a[k1 + 1] = xi; 277 | j1 += m2; 278 | k1 += 2 * m2; 279 | xr = a[j1]; 280 | xi = a[j1 + 1]; 281 | yr = a[k1]; 282 | yi = a[k1 + 1]; 283 | a[j1] = yr; 284 | a[j1 + 1] = yi; 285 | a[k1] = xr; 286 | a[k1 + 1] = xi; 287 | } 288 | j1 = 2 * k + m2 + ip[k]; 289 | k1 = j1 + m2; 290 | xr = a[j1]; 291 | xi = a[j1 + 1]; 292 | yr = a[k1]; 293 | yi = a[k1 + 1]; 294 | a[j1] = yr; 295 | a[j1 + 1] = yi; 296 | a[k1] = xr; 297 | a[k1 + 1] = xi; 298 | } 299 | } else { 300 | for (k = 1; k < m; k++) { 301 | for (j = 0; j < k; j++) { 302 | j1 = 2 * j + ip[k]; 303 | k1 = 2 * k + ip[j]; 304 | xr = a[j1]; 305 | xi = a[j1 + 1]; 306 | yr = a[k1]; 307 | yi = a[k1 + 1]; 308 | a[j1] = yr; 309 | a[j1 + 1] = yi; 310 | a[k1] = xr; 311 | a[k1 + 1] = xi; 312 | j1 += m2; 313 | k1 += m2; 314 | xr = a[j1]; 315 | xi = a[j1 + 1]; 316 | yr = a[k1]; 317 | yi = a[k1 + 1]; 318 | a[j1] = yr; 319 | a[j1 + 1] = yi; 320 | a[k1] = xr; 321 | a[k1 + 1] = xi; 322 | } 323 | } 324 | } 325 | } 326 | 327 | static void cftfsub(size_t n, float *a, float *w) { 328 | size_t j, j1, j2, j3, l; 329 | float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; 330 | 331 | l = 2; 332 | if (n > 8) { 333 | cft1st(n, a, w); 334 | l = 8; 335 | while ((l << 2) < n) { 336 | cftmdl(n, l, a, w); 337 | l <<= 2; 338 | } 339 | } 340 | if ((l << 2) == n) { 341 | for (j = 0; j < l; j += 2) { 342 | j1 = j + l; 343 | j2 = j1 + l; 344 | j3 = j2 + l; 345 | x0r = a[j] + a[j1]; 346 | x0i = a[j + 1] + a[j1 + 1]; 347 | x1r = a[j] - a[j1]; 348 | x1i = a[j + 1] - a[j1 + 1]; 349 | x2r = a[j2] + a[j3]; 350 | x2i = a[j2 + 1] + a[j3 + 1]; 351 | x3r = a[j2] - a[j3]; 352 | x3i = a[j2 + 1] - a[j3 + 1]; 353 | a[j] = x0r + x2r; 354 | a[j + 1] = x0i + x2i; 355 | a[j2] = x0r - x2r; 356 | a[j2 + 1] = x0i - x2i; 357 | a[j1] = x1r - x3i; 358 | a[j1 + 1] = x1i + x3r; 359 | a[j3] = x1r + x3i; 360 | a[j3 + 1] = x1i - x3r; 361 | } 362 | } else { 363 | for (j = 0; j < l; j += 2) { 364 | j1 = j + l; 365 | x0r = a[j] - a[j1]; 366 | x0i = a[j + 1] - a[j1 + 1]; 367 | a[j] += a[j1]; 368 | a[j + 1] += a[j1 + 1]; 369 | a[j1] = x0r; 370 | a[j1 + 1] = x0i; 371 | } 372 | } 373 | } 374 | 375 | 376 | static void cftbsub(size_t n, float *a, float *w) { 377 | size_t j, j1, j2, j3, l; 378 | float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; 379 | 380 | l = 2; 381 | if (n > 8) { 382 | cft1st(n, a, w); 383 | l = 8; 384 | while ((l << 2) < n) { 385 | cftmdl(n, l, a, w); 386 | l <<= 2; 387 | } 388 | } 389 | if ((l << 2) == n) { 390 | for (j = 0; j < l; j += 2) { 391 | j1 = j + l; 392 | j2 = j1 + l; 393 | j3 = j2 + l; 394 | x0r = a[j] + a[j1]; 395 | x0i = -a[j + 1] - a[j1 + 1]; 396 | x1r = a[j] - a[j1]; 397 | x1i = -a[j + 1] + a[j1 + 1]; 398 | x2r = a[j2] + a[j3]; 399 | x2i = a[j2 + 1] + a[j3 + 1]; 400 | x3r = a[j2] - a[j3]; 401 | x3i = a[j2 + 1] - a[j3 + 1]; 402 | a[j] = x0r + x2r; 403 | a[j + 1] = x0i - x2i; 404 | a[j2] = x0r - x2r; 405 | a[j2 + 1] = x0i + x2i; 406 | a[j1] = x1r - x3i; 407 | a[j1 + 1] = x1i - x3r; 408 | a[j3] = x1r + x3i; 409 | a[j3 + 1] = x1i + x3r; 410 | } 411 | } else { 412 | for (j = 0; j < l; j += 2) { 413 | j1 = j + l; 414 | x0r = a[j] - a[j1]; 415 | x0i = -a[j + 1] + a[j1 + 1]; 416 | a[j] += a[j1]; 417 | a[j + 1] = -a[j + 1] - a[j1 + 1]; 418 | a[j1] = x0r; 419 | a[j1 + 1] = x0i; 420 | } 421 | } 422 | } 423 | 424 | 425 | static void cft1st(size_t n, float *a, float *w) { 426 | size_t j, k1, k2; 427 | float wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; 428 | float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; 429 | 430 | x0r = a[0] + a[2]; 431 | x0i = a[1] + a[3]; 432 | x1r = a[0] - a[2]; 433 | x1i = a[1] - a[3]; 434 | x2r = a[4] + a[6]; 435 | x2i = a[5] + a[7]; 436 | x3r = a[4] - a[6]; 437 | x3i = a[5] - a[7]; 438 | a[0] = x0r + x2r; 439 | a[1] = x0i + x2i; 440 | a[4] = x0r - x2r; 441 | a[5] = x0i - x2i; 442 | a[2] = x1r - x3i; 443 | a[3] = x1i + x3r; 444 | a[6] = x1r + x3i; 445 | a[7] = x1i - x3r; 446 | wk1r = w[2]; 447 | x0r = a[8] + a[10]; 448 | x0i = a[9] + a[11]; 449 | x1r = a[8] - a[10]; 450 | x1i = a[9] - a[11]; 451 | x2r = a[12] + a[14]; 452 | x2i = a[13] + a[15]; 453 | x3r = a[12] - a[14]; 454 | x3i = a[13] - a[15]; 455 | a[8] = x0r + x2r; 456 | a[9] = x0i + x2i; 457 | a[12] = x2i - x0i; 458 | a[13] = x0r - x2r; 459 | x0r = x1r - x3i; 460 | x0i = x1i + x3r; 461 | a[10] = wk1r * (x0r - x0i); 462 | a[11] = wk1r * (x0r + x0i); 463 | x0r = x3i + x1r; 464 | x0i = x3r - x1i; 465 | a[14] = wk1r * (x0i - x0r); 466 | a[15] = wk1r * (x0i + x0r); 467 | k1 = 0; 468 | for (j = 16; j < n; j += 16) { 469 | k1 += 2; 470 | k2 = 2 * k1; 471 | wk2r = w[k1]; 472 | wk2i = w[k1 + 1]; 473 | wk1r = w[k2]; 474 | wk1i = w[k2 + 1]; 475 | wk3r = wk1r - 2 * wk2i * wk1i; 476 | wk3i = 2 * wk2i * wk1r - wk1i; 477 | x0r = a[j] + a[j + 2]; 478 | x0i = a[j + 1] + a[j + 3]; 479 | x1r = a[j] - a[j + 2]; 480 | x1i = a[j + 1] - a[j + 3]; 481 | x2r = a[j + 4] + a[j + 6]; 482 | x2i = a[j + 5] + a[j + 7]; 483 | x3r = a[j + 4] - a[j + 6]; 484 | x3i = a[j + 5] - a[j + 7]; 485 | a[j] = x0r + x2r; 486 | a[j + 1] = x0i + x2i; 487 | x0r -= x2r; 488 | x0i -= x2i; 489 | a[j + 4] = wk2r * x0r - wk2i * x0i; 490 | a[j + 5] = wk2r * x0i + wk2i * x0r; 491 | x0r = x1r - x3i; 492 | x0i = x1i + x3r; 493 | a[j + 2] = wk1r * x0r - wk1i * x0i; 494 | a[j + 3] = wk1r * x0i + wk1i * x0r; 495 | x0r = x1r + x3i; 496 | x0i = x1i - x3r; 497 | a[j + 6] = wk3r * x0r - wk3i * x0i; 498 | a[j + 7] = wk3r * x0i + wk3i * x0r; 499 | wk1r = w[k2 + 2]; 500 | wk1i = w[k2 + 3]; 501 | wk3r = wk1r - 2 * wk2r * wk1i; 502 | wk3i = 2 * wk2r * wk1r - wk1i; 503 | x0r = a[j + 8] + a[j + 10]; 504 | x0i = a[j + 9] + a[j + 11]; 505 | x1r = a[j + 8] - a[j + 10]; 506 | x1i = a[j + 9] - a[j + 11]; 507 | x2r = a[j + 12] + a[j + 14]; 508 | x2i = a[j + 13] + a[j + 15]; 509 | x3r = a[j + 12] - a[j + 14]; 510 | x3i = a[j + 13] - a[j + 15]; 511 | a[j + 8] = x0r + x2r; 512 | a[j + 9] = x0i + x2i; 513 | x0r -= x2r; 514 | x0i -= x2i; 515 | a[j + 12] = -wk2i * x0r - wk2r * x0i; 516 | a[j + 13] = -wk2i * x0i + wk2r * x0r; 517 | x0r = x1r - x3i; 518 | x0i = x1i + x3r; 519 | a[j + 10] = wk1r * x0r - wk1i * x0i; 520 | a[j + 11] = wk1r * x0i + wk1i * x0r; 521 | x0r = x1r + x3i; 522 | x0i = x1i - x3r; 523 | a[j + 14] = wk3r * x0r - wk3i * x0i; 524 | a[j + 15] = wk3r * x0i + wk3i * x0r; 525 | } 526 | } 527 | 528 | 529 | static void cftmdl(size_t n, size_t l, float *a, float *w) { 530 | size_t j, j1, j2, j3, k, k1, k2, m, m2; 531 | float wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; 532 | float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; 533 | 534 | m = l << 2; 535 | for (j = 0; j < l; j += 2) { 536 | j1 = j + l; 537 | j2 = j1 + l; 538 | j3 = j2 + l; 539 | x0r = a[j] + a[j1]; 540 | x0i = a[j + 1] + a[j1 + 1]; 541 | x1r = a[j] - a[j1]; 542 | x1i = a[j + 1] - a[j1 + 1]; 543 | x2r = a[j2] + a[j3]; 544 | x2i = a[j2 + 1] + a[j3 + 1]; 545 | x3r = a[j2] - a[j3]; 546 | x3i = a[j2 + 1] - a[j3 + 1]; 547 | a[j] = x0r + x2r; 548 | a[j + 1] = x0i + x2i; 549 | a[j2] = x0r - x2r; 550 | a[j2 + 1] = x0i - x2i; 551 | a[j1] = x1r - x3i; 552 | a[j1 + 1] = x1i + x3r; 553 | a[j3] = x1r + x3i; 554 | a[j3 + 1] = x1i - x3r; 555 | } 556 | wk1r = w[2]; 557 | for (j = m; j < l + m; j += 2) { 558 | j1 = j + l; 559 | j2 = j1 + l; 560 | j3 = j2 + l; 561 | x0r = a[j] + a[j1]; 562 | x0i = a[j + 1] + a[j1 + 1]; 563 | x1r = a[j] - a[j1]; 564 | x1i = a[j + 1] - a[j1 + 1]; 565 | x2r = a[j2] + a[j3]; 566 | x2i = a[j2 + 1] + a[j3 + 1]; 567 | x3r = a[j2] - a[j3]; 568 | x3i = a[j2 + 1] - a[j3 + 1]; 569 | a[j] = x0r + x2r; 570 | a[j + 1] = x0i + x2i; 571 | a[j2] = x2i - x0i; 572 | a[j2 + 1] = x0r - x2r; 573 | x0r = x1r - x3i; 574 | x0i = x1i + x3r; 575 | a[j1] = wk1r * (x0r - x0i); 576 | a[j1 + 1] = wk1r * (x0r + x0i); 577 | x0r = x3i + x1r; 578 | x0i = x3r - x1i; 579 | a[j3] = wk1r * (x0i - x0r); 580 | a[j3 + 1] = wk1r * (x0i + x0r); 581 | } 582 | k1 = 0; 583 | m2 = 2 * m; 584 | for (k = m2; k < n; k += m2) { 585 | k1 += 2; 586 | k2 = 2 * k1; 587 | wk2r = w[k1]; 588 | wk2i = w[k1 + 1]; 589 | wk1r = w[k2]; 590 | wk1i = w[k2 + 1]; 591 | wk3r = wk1r - 2 * wk2i * wk1i; 592 | wk3i = 2 * wk2i * wk1r - wk1i; 593 | for (j = k; j < l + k; j += 2) { 594 | j1 = j + l; 595 | j2 = j1 + l; 596 | j3 = j2 + l; 597 | x0r = a[j] + a[j1]; 598 | x0i = a[j + 1] + a[j1 + 1]; 599 | x1r = a[j] - a[j1]; 600 | x1i = a[j + 1] - a[j1 + 1]; 601 | x2r = a[j2] + a[j3]; 602 | x2i = a[j2 + 1] + a[j3 + 1]; 603 | x3r = a[j2] - a[j3]; 604 | x3i = a[j2 + 1] - a[j3 + 1]; 605 | a[j] = x0r + x2r; 606 | a[j + 1] = x0i + x2i; 607 | x0r -= x2r; 608 | x0i -= x2i; 609 | a[j2] = wk2r * x0r - wk2i * x0i; 610 | a[j2 + 1] = wk2r * x0i + wk2i * x0r; 611 | x0r = x1r - x3i; 612 | x0i = x1i + x3r; 613 | a[j1] = wk1r * x0r - wk1i * x0i; 614 | a[j1 + 1] = wk1r * x0i + wk1i * x0r; 615 | x0r = x1r + x3i; 616 | x0i = x1i - x3r; 617 | a[j3] = wk3r * x0r - wk3i * x0i; 618 | a[j3 + 1] = wk3r * x0i + wk3i * x0r; 619 | } 620 | wk1r = w[k2 + 2]; 621 | wk1i = w[k2 + 3]; 622 | wk3r = wk1r - 2 * wk2r * wk1i; 623 | wk3i = 2 * wk2r * wk1r - wk1i; 624 | for (j = k + m; j < l + (k + m); j += 2) { 625 | j1 = j + l; 626 | j2 = j1 + l; 627 | j3 = j2 + l; 628 | x0r = a[j] + a[j1]; 629 | x0i = a[j + 1] + a[j1 + 1]; 630 | x1r = a[j] - a[j1]; 631 | x1i = a[j + 1] - a[j1 + 1]; 632 | x2r = a[j2] + a[j3]; 633 | x2i = a[j2 + 1] + a[j3 + 1]; 634 | x3r = a[j2] - a[j3]; 635 | x3i = a[j2 + 1] - a[j3 + 1]; 636 | a[j] = x0r + x2r; 637 | a[j + 1] = x0i + x2i; 638 | x0r -= x2r; 639 | x0i -= x2i; 640 | a[j2] = -wk2i * x0r - wk2r * x0i; 641 | a[j2 + 1] = -wk2i * x0i + wk2r * x0r; 642 | x0r = x1r - x3i; 643 | x0i = x1i + x3r; 644 | a[j1] = wk1r * x0r - wk1i * x0i; 645 | a[j1 + 1] = wk1r * x0i + wk1i * x0r; 646 | x0r = x1r + x3i; 647 | x0i = x1i - x3r; 648 | a[j3] = wk3r * x0r - wk3i * x0i; 649 | a[j3 + 1] = wk3r * x0i + wk3i * x0r; 650 | } 651 | } 652 | } 653 | 654 | 655 | static void rftfsub(size_t n, float *a, size_t nc, float *c) { 656 | size_t j, k, kk, ks, m; 657 | float wkr, wki, xr, xi, yr, yi; 658 | 659 | m = n >> 1; 660 | ks = 2 * nc / m; 661 | kk = 0; 662 | for (j = 2; j < m; j += 2) { 663 | k = n - j; 664 | kk += ks; 665 | wkr = 0.5f - c[nc - kk]; 666 | wki = c[kk]; 667 | xr = a[j] - a[k]; 668 | xi = a[j + 1] + a[k + 1]; 669 | yr = wkr * xr - wki * xi; 670 | yi = wkr * xi + wki * xr; 671 | a[j] -= yr; 672 | a[j + 1] -= yi; 673 | a[k] += yr; 674 | a[k + 1] -= yi; 675 | } 676 | } 677 | 678 | 679 | static void rftbsub(size_t n, float *a, size_t nc, float *c) { 680 | size_t j, k, kk, ks, m; 681 | float wkr, wki, xr, xi, yr, yi; 682 | 683 | a[1] = -a[1]; 684 | m = n >> 1; 685 | ks = 2 * nc / m; 686 | kk = 0; 687 | for (j = 2; j < m; j += 2) { 688 | k = n - j; 689 | kk += ks; 690 | wkr = 0.5f - c[nc - kk]; 691 | wki = c[kk]; 692 | xr = a[j] - a[k]; 693 | xi = a[j + 1] + a[k + 1]; 694 | yr = wkr * xr + wki * xi; 695 | yi = wkr * xi - wki * xr; 696 | a[j] -= yr; 697 | a[j + 1] = yi - a[j + 1]; 698 | a[k] += yr; 699 | a[k + 1] = yi - a[k + 1]; 700 | } 701 | a[m + 1] = -a[m + 1]; 702 | } 703 | 704 | 705 | // Set Feature Extraction Parameters. 706 | static void set_feature_extraction_parameters(NoiseSuppressionC *self) { 707 | // Bin size of histogram. 708 | self->featureExtractionParams.binSizeLrt = 0.1f; 709 | self->featureExtractionParams.binSizeSpecFlat = 0.05f; 710 | self->featureExtractionParams.binSizeSpecDiff = 0.1f; 711 | 712 | // Range of histogram over which LRT threshold is computed. 713 | self->featureExtractionParams.rangeAvgHistLrt = 1.f; 714 | 715 | // Scale parameters: multiply dominant peaks of the histograms by scale factor 716 | // to obtain thresholds for prior model. 717 | // For LRT and spectral difference. 718 | self->featureExtractionParams.factor1ModelPars = 1.2f; 719 | // For spectral_flatness: used when noise is flatter than speech. 720 | self->featureExtractionParams.factor2ModelPars = 0.9f; 721 | 722 | // Peak limit for spectral flatness (varies between 0 and 1). 723 | self->featureExtractionParams.thresPosSpecFlat = 0.6f; 724 | 725 | // Limit on spacing of two highest peaks in histogram: spacing determined by 726 | // bin size. 727 | self->featureExtractionParams.limitPeakSpacingSpecFlat = 728 | 2 * self->featureExtractionParams.binSizeSpecFlat; 729 | self->featureExtractionParams.limitPeakSpacingSpecDiff = 730 | 2 * self->featureExtractionParams.binSizeSpecDiff; 731 | 732 | // Limit on relevance of second peak. 733 | self->featureExtractionParams.limitPeakWeightsSpecFlat = 0.5f; 734 | self->featureExtractionParams.limitPeakWeightsSpecDiff = 0.5f; 735 | 736 | // Fluctuation limit of LRT feature. 737 | self->featureExtractionParams.thresFluctLrt = 0.05f; 738 | 739 | // Limit on the max and min values for the feature thresholds. 740 | self->featureExtractionParams.maxLrt = 1.f; 741 | self->featureExtractionParams.minLrt = 0.2f; 742 | 743 | self->featureExtractionParams.maxSpecFlat = 0.95f; 744 | self->featureExtractionParams.minSpecFlat = 0.1f; 745 | 746 | self->featureExtractionParams.maxSpecDiff = 1.f; 747 | self->featureExtractionParams.minSpecDiff = 0.16f; 748 | 749 | // Criteria of weight of histogram peak to accept/reject feature. 750 | self->featureExtractionParams.thresWeightSpecFlat = 751 | (int) (0.3 * (self->modelUpdatePars[1])); // For spectral flatness. 752 | self->featureExtractionParams.thresWeightSpecDiff = 753 | (int) (0.3 * (self->modelUpdatePars[1])); // For spectral difference. 754 | } 755 | 756 | // Initialize state. 757 | int WebRtcNs_InitCore(NoiseSuppressionC *self, uint32_t fs) { 758 | int i; 759 | // Check for valid pointer. 760 | if (self == NULL) { 761 | return -1; 762 | } 763 | 764 | // Initialization of struct. 765 | if (fs == 8000 || fs == 16000 || fs == 32000 || fs == 48000 || fs == 44100) { 766 | self->fs = fs; 767 | } else { 768 | return -1; 769 | } 770 | self->windShift = 0; 771 | // We only support 10ms frames. 772 | if (fs == 8000) { 773 | self->blockLen = 80; 774 | self->anaLen = 128; 775 | self->window = kBlocks80w128; 776 | } else { 777 | self->blockLen = 160; 778 | self->anaLen = 256; 779 | self->window = kBlocks160w256; 780 | } 781 | self->magnLen = self->anaLen / 2 + 1; // Number of frequency bins. 782 | 783 | // Initialize FFT work arrays. 784 | self->ip[0] = 0; // Setting this triggers initialization. 785 | memset(self->dataBuf, 0, sizeof(float) * ANAL_BLOCKL_MAX); 786 | WebRtc_rdft(self->anaLen, 1, self->dataBuf, self->ip, self->wfft); 787 | 788 | memset(self->analyzeBuf, 0, sizeof(float) * ANAL_BLOCKL_MAX); 789 | memset(self->dataBuf, 0, sizeof(float) * ANAL_BLOCKL_MAX); 790 | memset(self->syntBuf, 0, sizeof(float) * ANAL_BLOCKL_MAX); 791 | 792 | // For HB processing. 793 | memset(self->dataBufHB, 794 | 0, 795 | sizeof(float) * NUM_HIGH_BANDS_MAX * ANAL_BLOCKL_MAX); 796 | 797 | // For quantile noise estimation. 798 | memset(self->quantile, 0, sizeof(float) * HALF_ANAL_BLOCKL); 799 | for (i = 0; i < SIMULT * HALF_ANAL_BLOCKL; i++) { 800 | self->lquantile[i] = 8.f; 801 | self->density[i] = 0.3f; 802 | } 803 | 804 | for (i = 0; i < SIMULT; i++) { 805 | self->counter[i] = 806 | (int) floorf((float) (END_STARTUP_LONG * (i + 1)) / (float) SIMULT); 807 | } 808 | 809 | self->updates = 0; 810 | 811 | // Wiener filter initialization. 812 | for (i = 0; i < HALF_ANAL_BLOCKL; i++) { 813 | self->smooth[i] = 1.f; 814 | } 815 | 816 | // Set the aggressiveness: default. 817 | self->aggrMode = 0; 818 | 819 | // Initialize variables for new method. 820 | self->priorSpeechProb = 0.5f; // Prior prob for speech/noise. 821 | // Previous analyze mag spectrum. 822 | memset(self->magnPrevAnalyze, 0, sizeof(float) * HALF_ANAL_BLOCKL); 823 | // Previous process mag spectrum. 824 | memset(self->magnPrevProcess, 0, sizeof(float) * HALF_ANAL_BLOCKL); 825 | // Current noise-spectrum. 826 | memset(self->noise, 0, sizeof(float) * HALF_ANAL_BLOCKL); 827 | // Previous noise-spectrum. 828 | memset(self->noisePrev, 0, sizeof(float) * HALF_ANAL_BLOCKL); 829 | // Conservative noise spectrum estimate. 830 | memset(self->magnAvgPause, 0, sizeof(float) * HALF_ANAL_BLOCKL); 831 | // For estimation of HB in second pass. 832 | memset(self->speechProb, 0, sizeof(float) * HALF_ANAL_BLOCKL); 833 | // Initial average magnitude spectrum. 834 | memset(self->initMagnEst, 0, sizeof(float) * HALF_ANAL_BLOCKL); 835 | for (i = 0; i < HALF_ANAL_BLOCKL; i++) { 836 | // Smooth LR (same as threshold). 837 | self->logLrtTimeAvg[i] = LRT_FEATURE_THR; 838 | } 839 | 840 | // Feature quantities. 841 | // Spectral flatness (start on threshold). 842 | self->featureData[0] = SF_FEATURE_THR; 843 | self->featureData[1] = 0.f; // Spectral entropy: not used in this version. 844 | self->featureData[2] = 0.f; // Spectral variance: not used in this version. 845 | // Average LRT factor (start on threshold). 846 | self->featureData[3] = LRT_FEATURE_THR; 847 | // Spectral template diff (start on threshold). 848 | self->featureData[4] = SF_FEATURE_THR; 849 | self->featureData[5] = 0.f; // Normalization for spectral difference. 850 | // Window time-average of input magnitude spectrum. 851 | self->featureData[6] = 0.f; 852 | 853 | // Histogram quantities: used to estimate/update thresholds for features. 854 | memset(self->histLrt, 0, sizeof(int) * HIST_PAR_EST); 855 | memset(self->histSpecFlat, 0, sizeof(int) * HIST_PAR_EST); 856 | memset(self->histSpecDiff, 0, sizeof(int) * HIST_PAR_EST); 857 | 858 | 859 | self->blockInd = -1; // Frame counter. 860 | // Default threshold for LRT feature. 861 | self->priorModelPars[0] = LRT_FEATURE_THR; 862 | // Threshold for spectral flatness: determined on-line. 863 | self->priorModelPars[1] = 0.5f; 864 | // sgn_map par for spectral measure: 1 for flatness measure. 865 | self->priorModelPars[2] = 1.f; 866 | // Threshold for template-difference feature: determined on-line. 867 | self->priorModelPars[3] = 0.5f; 868 | // Default weighting parameter for LRT feature. 869 | self->priorModelPars[4] = 1.f; 870 | // Default weighting parameter for spectral flatness feature. 871 | self->priorModelPars[5] = 0.f; 872 | // Default weighting parameter for spectral difference feature. 873 | self->priorModelPars[6] = 0.f; 874 | 875 | // Update flag for parameters: 876 | // 0 no update, 1 = update once, 2 = update every window. 877 | self->modelUpdatePars[0] = 2; 878 | self->modelUpdatePars[1] = 500; // Window for update. 879 | // Counter for update of conservative noise spectrum. 880 | self->modelUpdatePars[2] = 0; 881 | // Counter if the feature thresholds are updated during the sequence. 882 | self->modelUpdatePars[3] = self->modelUpdatePars[1]; 883 | 884 | self->signalEnergy = 0.0; 885 | self->sumMagn = 0.0; 886 | self->whiteNoiseLevel = 0.0; 887 | self->pinkNoiseNumerator = 0.0; 888 | self->pinkNoiseExp = 0.0; 889 | 890 | set_feature_extraction_parameters(self); 891 | 892 | // Default mode. 893 | WebRtcNs_set_policy_core(self, 0); 894 | 895 | self->initFlag = 1; 896 | return 0; 897 | } 898 | 899 | // Estimate noise. 900 | static void NoiseEstimation(NoiseSuppressionC *self, 901 | float *magn, 902 | float *noise) { 903 | size_t i, s, offset = 0; 904 | float lmagn[HALF_ANAL_BLOCKL], delta; 905 | 906 | if (self->updates < END_STARTUP_LONG) { 907 | self->updates++; 908 | } 909 | 910 | for (i = 0; i < self->magnLen; i++) { 911 | lmagn[i] = logf(magn[i]); 912 | } 913 | 914 | // Loop over simultaneous estimates. 915 | for (s = 0; s < SIMULT; s++) { 916 | offset = s * self->magnLen; 917 | 918 | // newquantest(...) 919 | for (i = 0; i < self->magnLen; i++) { 920 | // Compute delta. 921 | if (self->density[offset + i] > 1.0) { 922 | delta = FACTOR * 1.f / self->density[offset + i]; 923 | } else { 924 | delta = FACTOR; 925 | } 926 | 927 | // Update log quantile estimate. 928 | if (lmagn[i] > self->lquantile[offset + i]) { 929 | self->lquantile[offset + i] += 930 | QUANTILE * delta / (float) (self->counter[s] + 1); 931 | } else { 932 | self->lquantile[offset + i] -= 933 | (1.f - QUANTILE) * delta / (float) (self->counter[s] + 1); 934 | } 935 | 936 | // Update density estimate. 937 | if (fabsf(lmagn[i] - self->lquantile[offset + i]) < WIDTH) { 938 | self->density[offset + i] = 939 | ((float) self->counter[s] * self->density[offset + i] + 940 | 1.f / (2.f * WIDTH)) / 941 | (float) (self->counter[s] + 1); 942 | } 943 | } // End loop over magnitude spectrum. 944 | 945 | if (self->counter[s] >= END_STARTUP_LONG) { 946 | self->counter[s] = 0; 947 | if (self->updates >= END_STARTUP_LONG) { 948 | for (i = 0; i < self->magnLen; i++) { 949 | self->quantile[i] = expf(self->lquantile[offset + i]); 950 | } 951 | } 952 | } 953 | 954 | self->counter[s]++; 955 | } // End loop over simultaneous estimates. 956 | 957 | // Sequentially update the noise during startup. 958 | if (self->updates < END_STARTUP_LONG) { 959 | // Use the last "s" to get noise during startup that differ from zero. 960 | for (i = 0; i < self->magnLen; i++) { 961 | self->quantile[i] = expf(self->lquantile[offset + i]); 962 | } 963 | } 964 | 965 | for (i = 0; i < self->magnLen; i++) { 966 | noise[i] = self->quantile[i]; 967 | } 968 | } 969 | 970 | // Extract thresholds for feature parameters. 971 | // Histograms are computed over some window size (given by 972 | // self->modelUpdatePars[1]). 973 | // Thresholds and weights are extracted every window. 974 | // |flag| = 0 updates histogram only, |flag| = 1 computes the threshold/weights. 975 | // Threshold and weights are returned in: self->priorModelPars. 976 | static void FeatureParameterExtraction(NoiseSuppressionC *self, int flag) { 977 | int i, useFeatureSpecFlat, useFeatureSpecDiff, numHistLrt; 978 | int maxPeak1, maxPeak2; 979 | int weightPeak1SpecFlat, weightPeak2SpecFlat, weightPeak1SpecDiff, 980 | weightPeak2SpecDiff; 981 | 982 | float binMid, featureSum; 983 | float posPeak1SpecFlat, posPeak2SpecFlat, posPeak1SpecDiff, posPeak2SpecDiff; 984 | float fluctLrt, avgHistLrt, avgSquareHistLrt, avgHistLrtCompl; 985 | 986 | // 3 features: LRT, flatness, difference. 987 | // lrt_feature = self->featureData[3]; 988 | // flat_feature = self->featureData[0]; 989 | // diff_feature = self->featureData[4]; 990 | 991 | // Update histograms. 992 | if (flag == 0) { 993 | // LRT 994 | if ((self->featureData[3] < 995 | HIST_PAR_EST * self->featureExtractionParams.binSizeLrt) && 996 | (self->featureData[3] >= 0.0)) { 997 | i = (int) (self->featureData[3] / 998 | self->featureExtractionParams.binSizeLrt); 999 | self->histLrt[i]++; 1000 | } 1001 | // Spectral flatness. 1002 | if ((self->featureData[0] < 1003 | HIST_PAR_EST * self->featureExtractionParams.binSizeSpecFlat) && 1004 | (self->featureData[0] >= 0.0)) { 1005 | i = (int) (self->featureData[0] / 1006 | self->featureExtractionParams.binSizeSpecFlat); 1007 | self->histSpecFlat[i]++; 1008 | } 1009 | // Spectral difference. 1010 | if ((self->featureData[4] < 1011 | HIST_PAR_EST * self->featureExtractionParams.binSizeSpecDiff) && 1012 | (self->featureData[4] >= 0.0)) { 1013 | i = (int) (self->featureData[4] / 1014 | self->featureExtractionParams.binSizeSpecDiff); 1015 | self->histSpecDiff[i]++; 1016 | } 1017 | } 1018 | 1019 | // Extract parameters for speech/noise probability. 1020 | if (flag == 1) { 1021 | // LRT feature: compute the average over 1022 | // self->featureExtractionParams.rangeAvgHistLrt. 1023 | avgHistLrt = 0.0; 1024 | avgHistLrtCompl = 0.0; 1025 | avgSquareHistLrt = 0.0; 1026 | numHistLrt = 0; 1027 | for (i = 0; i < HIST_PAR_EST; i++) { 1028 | binMid = ((float) i + 0.5f) * self->featureExtractionParams.binSizeLrt; 1029 | if (binMid <= self->featureExtractionParams.rangeAvgHistLrt) { 1030 | avgHistLrt += self->histLrt[i] * binMid; 1031 | numHistLrt += self->histLrt[i]; 1032 | } 1033 | avgSquareHistLrt += self->histLrt[i] * binMid * binMid; 1034 | avgHistLrtCompl += self->histLrt[i] * binMid; 1035 | } 1036 | if (numHistLrt > 0) { 1037 | avgHistLrt = avgHistLrt / ((float) numHistLrt); 1038 | } 1039 | avgHistLrtCompl = avgHistLrtCompl / ((float) self->modelUpdatePars[1]); 1040 | avgSquareHistLrt = avgSquareHistLrt / ((float) self->modelUpdatePars[1]); 1041 | fluctLrt = avgSquareHistLrt - avgHistLrt * avgHistLrtCompl; 1042 | // Get threshold for LRT feature. 1043 | if (fluctLrt < self->featureExtractionParams.thresFluctLrt) { 1044 | // Very low fluctuation, so likely noise. 1045 | self->priorModelPars[0] = self->featureExtractionParams.maxLrt; 1046 | } else { 1047 | self->priorModelPars[0] = 1048 | self->featureExtractionParams.factor1ModelPars * avgHistLrt; 1049 | // Check if value is within min/max range. 1050 | if (self->priorModelPars[0] < self->featureExtractionParams.minLrt) { 1051 | self->priorModelPars[0] = self->featureExtractionParams.minLrt; 1052 | } 1053 | if (self->priorModelPars[0] > self->featureExtractionParams.maxLrt) { 1054 | self->priorModelPars[0] = self->featureExtractionParams.maxLrt; 1055 | } 1056 | } 1057 | // Done with LRT feature. 1058 | 1059 | // For spectral flatness and spectral difference: compute the main peaks of 1060 | // histogram. 1061 | maxPeak1 = 0; 1062 | maxPeak2 = 0; 1063 | posPeak1SpecFlat = 0.0; 1064 | posPeak2SpecFlat = 0.0; 1065 | weightPeak1SpecFlat = 0; 1066 | weightPeak2SpecFlat = 0; 1067 | 1068 | // Peaks for flatness. 1069 | for (i = 0; i < HIST_PAR_EST; i++) { 1070 | binMid = 1071 | (i + 0.5f) * self->featureExtractionParams.binSizeSpecFlat; 1072 | if (self->histSpecFlat[i] > maxPeak1) { 1073 | // Found new "first" peak. 1074 | maxPeak2 = maxPeak1; 1075 | weightPeak2SpecFlat = weightPeak1SpecFlat; 1076 | posPeak2SpecFlat = posPeak1SpecFlat; 1077 | 1078 | maxPeak1 = self->histSpecFlat[i]; 1079 | weightPeak1SpecFlat = self->histSpecFlat[i]; 1080 | posPeak1SpecFlat = binMid; 1081 | } else if (self->histSpecFlat[i] > maxPeak2) { 1082 | // Found new "second" peak. 1083 | maxPeak2 = self->histSpecFlat[i]; 1084 | weightPeak2SpecFlat = self->histSpecFlat[i]; 1085 | posPeak2SpecFlat = binMid; 1086 | } 1087 | } 1088 | 1089 | // Compute two peaks for spectral difference. 1090 | maxPeak1 = 0; 1091 | maxPeak2 = 0; 1092 | posPeak1SpecDiff = 0.0; 1093 | posPeak2SpecDiff = 0.0; 1094 | weightPeak1SpecDiff = 0; 1095 | weightPeak2SpecDiff = 0; 1096 | // Peaks for spectral difference. 1097 | for (i = 0; i < HIST_PAR_EST; i++) { 1098 | binMid = 1099 | ((float) i + 0.5f) * self->featureExtractionParams.binSizeSpecDiff; 1100 | if (self->histSpecDiff[i] > maxPeak1) { 1101 | // Found new "first" peak. 1102 | maxPeak2 = maxPeak1; 1103 | weightPeak2SpecDiff = weightPeak1SpecDiff; 1104 | posPeak2SpecDiff = posPeak1SpecDiff; 1105 | 1106 | maxPeak1 = self->histSpecDiff[i]; 1107 | weightPeak1SpecDiff = self->histSpecDiff[i]; 1108 | posPeak1SpecDiff = binMid; 1109 | } else if (self->histSpecDiff[i] > maxPeak2) { 1110 | // Found new "second" peak. 1111 | maxPeak2 = self->histSpecDiff[i]; 1112 | weightPeak2SpecDiff = self->histSpecDiff[i]; 1113 | posPeak2SpecDiff = binMid; 1114 | } 1115 | } 1116 | 1117 | // For spectrum flatness feature. 1118 | useFeatureSpecFlat = 1; 1119 | // Merge the two peaks if they are close. 1120 | if ((fabsf(posPeak2SpecFlat - posPeak1SpecFlat) < 1121 | self->featureExtractionParams.limitPeakSpacingSpecFlat) && 1122 | (weightPeak2SpecFlat > 1123 | self->featureExtractionParams.limitPeakWeightsSpecFlat * 1124 | weightPeak1SpecFlat)) { 1125 | weightPeak1SpecFlat += weightPeak2SpecFlat; 1126 | posPeak1SpecFlat = 0.5f * (posPeak1SpecFlat + posPeak2SpecFlat); 1127 | } 1128 | // Reject if weight of peaks is not large enough, or peak value too small. 1129 | if (weightPeak1SpecFlat < 1130 | self->featureExtractionParams.thresWeightSpecFlat || 1131 | posPeak1SpecFlat < self->featureExtractionParams.thresPosSpecFlat) { 1132 | useFeatureSpecFlat = 0; 1133 | } 1134 | // If selected, get the threshold. 1135 | if (useFeatureSpecFlat == 1) { 1136 | // Compute the threshold. 1137 | self->priorModelPars[1] = 1138 | self->featureExtractionParams.factor2ModelPars * posPeak1SpecFlat; 1139 | // Check if value is within min/max range. 1140 | if (self->priorModelPars[1] < self->featureExtractionParams.minSpecFlat) { 1141 | self->priorModelPars[1] = self->featureExtractionParams.minSpecFlat; 1142 | } 1143 | if (self->priorModelPars[1] > self->featureExtractionParams.maxSpecFlat) { 1144 | self->priorModelPars[1] = self->featureExtractionParams.maxSpecFlat; 1145 | } 1146 | } 1147 | // Done with flatness feature. 1148 | 1149 | // For template feature. 1150 | useFeatureSpecDiff = 1; 1151 | // Merge the two peaks if they are close. 1152 | if ((fabsf(posPeak2SpecDiff - posPeak1SpecDiff) < 1153 | self->featureExtractionParams.limitPeakSpacingSpecDiff) && 1154 | (weightPeak2SpecDiff > 1155 | self->featureExtractionParams.limitPeakWeightsSpecDiff * 1156 | weightPeak1SpecDiff)) { 1157 | weightPeak1SpecDiff += weightPeak2SpecDiff; 1158 | posPeak1SpecDiff = 0.5f * (posPeak1SpecDiff + posPeak2SpecDiff); 1159 | } 1160 | // Get the threshold value. 1161 | self->priorModelPars[3] = 1162 | self->featureExtractionParams.factor1ModelPars * posPeak1SpecDiff; 1163 | // Reject if weight of peaks is not large enough. 1164 | if (weightPeak1SpecDiff < 1165 | self->featureExtractionParams.thresWeightSpecDiff) { 1166 | useFeatureSpecDiff = 0; 1167 | } 1168 | // Check if value is within min/max range. 1169 | if (self->priorModelPars[3] < self->featureExtractionParams.minSpecDiff) { 1170 | self->priorModelPars[3] = self->featureExtractionParams.minSpecDiff; 1171 | } 1172 | if (self->priorModelPars[3] > self->featureExtractionParams.maxSpecDiff) { 1173 | self->priorModelPars[3] = self->featureExtractionParams.maxSpecDiff; 1174 | } 1175 | // Done with spectral difference feature. 1176 | 1177 | // Don't use template feature if fluctuation of LRT feature is very low: 1178 | // most likely just noise state. 1179 | if (fluctLrt < self->featureExtractionParams.thresFluctLrt) { 1180 | useFeatureSpecDiff = 0; 1181 | } 1182 | 1183 | // Select the weights between the features. 1184 | // self->priorModelPars[4] is weight for LRT: always selected. 1185 | // self->priorModelPars[5] is weight for spectral flatness. 1186 | // self->priorModelPars[6] is weight for spectral difference. 1187 | featureSum = (float) (1 + useFeatureSpecFlat + useFeatureSpecDiff); 1188 | self->priorModelPars[4] = 1.f / featureSum; 1189 | self->priorModelPars[5] = ((float) useFeatureSpecFlat) / featureSum; 1190 | self->priorModelPars[6] = ((float) useFeatureSpecDiff) / featureSum; 1191 | 1192 | // Set hists to zero for next update. 1193 | if (self->modelUpdatePars[0] >= 1) { 1194 | for (i = 0; i < HIST_PAR_EST; i++) { 1195 | self->histLrt[i] = 0; 1196 | self->histSpecFlat[i] = 0; 1197 | self->histSpecDiff[i] = 0; 1198 | } 1199 | } 1200 | } // End of flag == 1. 1201 | } 1202 | 1203 | // Compute spectral flatness on input spectrum. 1204 | // |magnIn| is the magnitude spectrum. 1205 | // Spectral flatness is returned in self->featureData[0]. 1206 | static void ComputeSpectralFlatness(NoiseSuppressionC *self, 1207 | const float *magnIn) { 1208 | size_t i; 1209 | size_t shiftLP = 1; // Option to remove first bin(s) from spectral measures. 1210 | float avgSpectralFlatnessNum, avgSpectralFlatnessDen, spectralTmp; 1211 | 1212 | // Compute spectral measures. 1213 | // For flatness. 1214 | avgSpectralFlatnessNum = 0.0; 1215 | avgSpectralFlatnessDen = self->sumMagn; 1216 | for (i = 0; i < shiftLP; i++) { 1217 | avgSpectralFlatnessDen -= magnIn[i]; 1218 | } 1219 | // Compute log of ratio of the geometric to arithmetic mean: check for log(0) 1220 | // case. 1221 | for (i = shiftLP; i < self->magnLen; i++) { 1222 | if (magnIn[i] > 0.0) { 1223 | avgSpectralFlatnessNum += logf(magnIn[i]); 1224 | } else { 1225 | self->featureData[0] -= SPECT_FL_TAVG * self->featureData[0]; 1226 | return; 1227 | } 1228 | } 1229 | // Normalize. 1230 | avgSpectralFlatnessDen = avgSpectralFlatnessDen / self->magnLen; 1231 | avgSpectralFlatnessNum = avgSpectralFlatnessNum / self->magnLen; 1232 | 1233 | // Ratio and inverse log: check for case of log(0). 1234 | spectralTmp = expf(avgSpectralFlatnessNum) / avgSpectralFlatnessDen; 1235 | 1236 | // Time-avg update of spectral flatness feature. 1237 | self->featureData[0] += SPECT_FL_TAVG * (spectralTmp - self->featureData[0]); 1238 | // Done with flatness feature. 1239 | } 1240 | 1241 | // Compute prior and post SNR based on quantile noise estimation. 1242 | // Compute DD estimate of prior SNR. 1243 | // Inputs: 1244 | // * |magn| is the signal magnitude spectrum estimate. 1245 | // * |noise| is the magnitude noise spectrum estimate. 1246 | // Outputs: 1247 | // * |snrLocPrior| is the computed prior SNR. 1248 | // * |snrLocPost| is the computed post SNR. 1249 | static void ComputeSnr(const NoiseSuppressionC *self, 1250 | const float *magn, 1251 | const float *noise, 1252 | float *snrLocPrior, 1253 | float *snrLocPost) { 1254 | size_t i; 1255 | 1256 | for (i = 0; i < self->magnLen; i++) { 1257 | // Previous post SNR. 1258 | // Previous estimate: based on previous frame with gain filter. 1259 | float previousEstimateStsa = self->magnPrevAnalyze[i] / 1260 | (self->noisePrev[i] + 0.0001f) * self->smooth[i]; 1261 | // Post SNR. 1262 | snrLocPost[i] = 0.f; 1263 | if (magn[i] > noise[i]) { 1264 | snrLocPost[i] = magn[i] / (noise[i] + 0.0001f) - 1.f; 1265 | } 1266 | // DD estimate is sum of two terms: current estimate and previous estimate. 1267 | // Directed decision update of snrPrior. 1268 | snrLocPrior[i] = 1269 | DD_PR_SNR * previousEstimateStsa + (1.f - DD_PR_SNR) * snrLocPost[i]; 1270 | } // End of loop over frequencies. 1271 | } 1272 | 1273 | // Compute the difference measure between input spectrum and a template/learned 1274 | // noise spectrum. 1275 | // |magnIn| is the input spectrum. 1276 | // The reference/template spectrum is self->magnAvgPause[i]. 1277 | // Returns (normalized) spectral difference in self->featureData[4]. 1278 | static void ComputeSpectralDifference(NoiseSuppressionC *self, 1279 | const float *magnIn) { 1280 | // avgDiffNormMagn = var(magnIn) - cov(magnIn, magnAvgPause)^2 / 1281 | // var(magnAvgPause) 1282 | size_t i; 1283 | float avgPause, avgMagn, covMagnPause, varPause, varMagn, avgDiffNormMagn; 1284 | 1285 | avgPause = 0.0; 1286 | avgMagn = self->sumMagn; 1287 | // Compute average quantities. 1288 | for (i = 0; i < self->magnLen; i++) { 1289 | // Conservative smooth noise spectrum from pause frames. 1290 | avgPause += self->magnAvgPause[i]; 1291 | } 1292 | avgPause /= self->magnLen; 1293 | avgMagn /= self->magnLen; 1294 | 1295 | covMagnPause = 0.0; 1296 | varPause = 0.0; 1297 | varMagn = 0.0; 1298 | // Compute variance and covariance quantities. 1299 | for (i = 0; i < self->magnLen; i++) { 1300 | covMagnPause += (magnIn[i] - avgMagn) * (self->magnAvgPause[i] - avgPause); 1301 | varPause += 1302 | (self->magnAvgPause[i] - avgPause) * (self->magnAvgPause[i] - avgPause); 1303 | varMagn += (magnIn[i] - avgMagn) * (magnIn[i] - avgMagn); 1304 | } 1305 | covMagnPause /= self->magnLen; 1306 | varPause /= self->magnLen; 1307 | varMagn /= self->magnLen; 1308 | // Update of average magnitude spectrum. 1309 | self->featureData[6] += self->signalEnergy; 1310 | 1311 | avgDiffNormMagn = 1312 | varMagn - (covMagnPause * covMagnPause) / (varPause + 0.0001f); 1313 | // Normalize and compute time-avg update of difference feature. 1314 | avgDiffNormMagn = avgDiffNormMagn / (self->featureData[5] + 0.0001f); 1315 | self->featureData[4] += 1316 | SPECT_DIFF_TAVG * (avgDiffNormMagn - self->featureData[4]); 1317 | } 1318 | 1319 | // Compute speech/noise probability. 1320 | // Speech/noise probability is returned in |probSpeechFinal|. 1321 | // |magn| is the input magnitude spectrum. 1322 | // |noise| is the noise spectrum. 1323 | // |snrLocPrior| is the prior SNR for each frequency. 1324 | // |snrLocPost| is the post SNR for each frequency. 1325 | static void SpeechNoiseProb(NoiseSuppressionC *self, 1326 | float *probSpeechFinal, 1327 | const float *snrLocPrior, 1328 | const float *snrLocPost) { 1329 | size_t i; 1330 | int sgnMap; 1331 | float invLrt, gainPrior, indPrior; 1332 | float logLrtTimeAvgKsum, besselTmp; 1333 | float indicator0, indicator1, indicator2; 1334 | float tmpFloat1, tmpFloat2; 1335 | float weightIndPrior0, weightIndPrior1, weightIndPrior2; 1336 | float threshPrior0, threshPrior1, threshPrior2; 1337 | float widthPrior, widthPrior0, widthPrior1, widthPrior2; 1338 | 1339 | widthPrior0 = WIDTH_PR_MAP; 1340 | // Width for pause region: lower range, so increase width in tanh map. 1341 | widthPrior1 = 2.f * WIDTH_PR_MAP; 1342 | widthPrior2 = 2.f * WIDTH_PR_MAP; // For spectral-difference measure. 1343 | 1344 | // Threshold parameters for features. 1345 | threshPrior0 = self->priorModelPars[0]; 1346 | threshPrior1 = self->priorModelPars[1]; 1347 | threshPrior2 = self->priorModelPars[3]; 1348 | 1349 | // Sign for flatness feature. 1350 | sgnMap = (int) (self->priorModelPars[2]); 1351 | 1352 | // Weight parameters for features. 1353 | weightIndPrior0 = self->priorModelPars[4]; 1354 | weightIndPrior1 = self->priorModelPars[5]; 1355 | weightIndPrior2 = self->priorModelPars[6]; 1356 | 1357 | // Compute feature based on average LR factor. 1358 | // This is the average over all frequencies of the smooth log LRT. 1359 | logLrtTimeAvgKsum = 0.0; 1360 | for (i = 0; i < self->magnLen; i++) { 1361 | tmpFloat1 = 1.f + 2.f * snrLocPrior[i]; 1362 | tmpFloat2 = 2.f * snrLocPrior[i] / (tmpFloat1 + 0.0001f); 1363 | besselTmp = (snrLocPost[i] + 1.f) * tmpFloat2; 1364 | self->logLrtTimeAvg[i] += 1365 | LRT_TAVG * (besselTmp - logf(tmpFloat1) - self->logLrtTimeAvg[i]); 1366 | logLrtTimeAvgKsum += self->logLrtTimeAvg[i]; 1367 | } 1368 | logLrtTimeAvgKsum = logLrtTimeAvgKsum / (self->magnLen); 1369 | self->featureData[3] = logLrtTimeAvgKsum; 1370 | // Done with computation of LR factor. 1371 | 1372 | // Compute the indicator functions. 1373 | // Average LRT feature. 1374 | widthPrior = widthPrior0; 1375 | // Use larger width in tanh map for pause regions. 1376 | if (logLrtTimeAvgKsum < threshPrior0) { 1377 | widthPrior = widthPrior1; 1378 | } 1379 | // Compute indicator function: sigmoid map. 1380 | indicator0 = 1381 | 0.5f * 1382 | (tanhf(widthPrior * (logLrtTimeAvgKsum - threshPrior0)) + 1.f); 1383 | 1384 | // Spectral flatness feature. 1385 | tmpFloat1 = self->featureData[0]; 1386 | widthPrior = widthPrior0; 1387 | // Use larger width in tanh map for pause regions. 1388 | if (sgnMap == 1 && (tmpFloat1 > threshPrior1)) { 1389 | widthPrior = widthPrior1; 1390 | } 1391 | if (sgnMap == -1 && (tmpFloat1 < threshPrior1)) { 1392 | widthPrior = widthPrior1; 1393 | } 1394 | // Compute indicator function: sigmoid map. 1395 | indicator1 = 1396 | 0.5f * 1397 | (tanhf((float) sgnMap * widthPrior * (threshPrior1 - tmpFloat1)) + 1398 | 1.f); 1399 | 1400 | // For template spectrum-difference. 1401 | tmpFloat1 = self->featureData[4]; 1402 | widthPrior = widthPrior0; 1403 | // Use larger width in tanh map for pause regions. 1404 | if (tmpFloat1 < threshPrior2) { 1405 | widthPrior = widthPrior2; 1406 | } 1407 | // Compute indicator function: sigmoid map. 1408 | indicator2 = 1409 | 0.5f * (tanhf(widthPrior * (tmpFloat1 - threshPrior2)) + 1.f); 1410 | 1411 | // Combine the indicator function with the feature weights. 1412 | indPrior = weightIndPrior0 * indicator0 + weightIndPrior1 * indicator1 + 1413 | weightIndPrior2 * indicator2; 1414 | // Done with computing indicator function. 1415 | 1416 | // Compute the prior probability. 1417 | self->priorSpeechProb += PRIOR_UPDATE * (indPrior - self->priorSpeechProb); 1418 | // Make sure probabilities are within range: keep floor to 0.01. 1419 | if (self->priorSpeechProb > 1.f) { 1420 | self->priorSpeechProb = 1.f; 1421 | } 1422 | if (self->priorSpeechProb < 0.01f) { 1423 | self->priorSpeechProb = 0.01f; 1424 | } 1425 | 1426 | // Final speech probability: combine prior model with LR factor:. 1427 | gainPrior = (1.f - self->priorSpeechProb) / (self->priorSpeechProb + 0.0001f); 1428 | for (i = 0; i < self->magnLen; i++) { 1429 | invLrt = expf(-self->logLrtTimeAvg[i]); 1430 | invLrt = gainPrior * invLrt; 1431 | probSpeechFinal[i] = 1.f / (1.f + invLrt); 1432 | } 1433 | } 1434 | 1435 | // Update the noise features. 1436 | // Inputs: 1437 | // * |magn| is the signal magnitude spectrum estimate. 1438 | // * |updateParsFlag| is an update flag for parameters. 1439 | static void FeatureUpdate(NoiseSuppressionC *self, 1440 | const float *magn, 1441 | int updateParsFlag) { 1442 | // Compute spectral flatness on input spectrum. 1443 | ComputeSpectralFlatness(self, magn); 1444 | // Compute difference of input spectrum with learned/estimated noise spectrum. 1445 | ComputeSpectralDifference(self, magn); 1446 | // Compute histograms for parameter decisions (thresholds and weights for 1447 | // features). 1448 | // Parameters are extracted once every window time. 1449 | // (=self->modelUpdatePars[1]) 1450 | if (updateParsFlag >= 1) { 1451 | // Counter update. 1452 | self->modelUpdatePars[3]--; 1453 | // Update histogram. 1454 | if (self->modelUpdatePars[3] > 0) { 1455 | FeatureParameterExtraction(self, 0); 1456 | } 1457 | // Compute model parameters. 1458 | if (self->modelUpdatePars[3] == 0) { 1459 | FeatureParameterExtraction(self, 1); 1460 | self->modelUpdatePars[3] = self->modelUpdatePars[1]; 1461 | // If wish to update only once, set flag to zero. 1462 | if (updateParsFlag == 1) { 1463 | self->modelUpdatePars[0] = 0; 1464 | } else { 1465 | // Update every window: 1466 | // Get normalization for spectral difference for next window estimate. 1467 | self->featureData[6] = 1468 | self->featureData[6] / ((float) self->modelUpdatePars[1]); 1469 | self->featureData[5] = 1470 | 0.5f * (self->featureData[6] + self->featureData[5]); 1471 | self->featureData[6] = 0.f; 1472 | } 1473 | } 1474 | } 1475 | } 1476 | 1477 | // Update the noise estimate. 1478 | // Inputs: 1479 | // * |magn| is the signal magnitude spectrum estimate. 1480 | // * |snrLocPrior| is the prior SNR. 1481 | // * |snrLocPost| is the post SNR. 1482 | // Output: 1483 | // * |noise| is the updated noise magnitude spectrum estimate. 1484 | static void UpdateNoiseEstimate(NoiseSuppressionC *self, 1485 | const float *magn, 1486 | float *noise) { 1487 | size_t i; 1488 | float probSpeech, probNonSpeech; 1489 | // Time-avg parameter for noise update. 1490 | float gammaNoiseTmp = NOISE_UPDATE; 1491 | float gammaNoiseOld; 1492 | float noiseUpdateTmp; 1493 | 1494 | for (i = 0; i < self->magnLen; i++) { 1495 | probSpeech = self->speechProb[i]; 1496 | probNonSpeech = 1.f - probSpeech; 1497 | // Temporary noise update: 1498 | // Use it for speech frames if update value is less than previous. 1499 | noiseUpdateTmp = gammaNoiseTmp * self->noisePrev[i] + 1500 | (1.f - gammaNoiseTmp) * (probNonSpeech * magn[i] + 1501 | probSpeech * self->noisePrev[i]); 1502 | // Time-constant based on speech/noise state. 1503 | gammaNoiseOld = gammaNoiseTmp; 1504 | gammaNoiseTmp = NOISE_UPDATE; 1505 | // Increase gamma (i.e., less noise update) for frame likely to be speech. 1506 | if (probSpeech > PROB_RANGE) { 1507 | gammaNoiseTmp = SPEECH_UPDATE; 1508 | } 1509 | // Conservative noise update. 1510 | if (probSpeech < PROB_RANGE) { 1511 | self->magnAvgPause[i] += GAMMA_PAUSE * (magn[i] - self->magnAvgPause[i]); 1512 | } 1513 | // Noise update. 1514 | if (gammaNoiseTmp == gammaNoiseOld) { 1515 | noise[i] = noiseUpdateTmp; 1516 | } else { 1517 | noise[i] = gammaNoiseTmp * self->noisePrev[i] + 1518 | (1.f - gammaNoiseTmp) * (probNonSpeech * magn[i] + 1519 | probSpeech * self->noisePrev[i]); 1520 | // Allow for noise update downwards: 1521 | // If noise update decreases the noise, it is safe, so allow it to 1522 | // happen. 1523 | if (noiseUpdateTmp < noise[i]) { 1524 | noise[i] = noiseUpdateTmp; 1525 | } 1526 | } 1527 | } // End of freq loop. 1528 | } 1529 | 1530 | // Updates |buffer| with a new |frame|. 1531 | // Inputs: 1532 | // * |frame| is a new speech frame or NULL for setting to zero. 1533 | // * |frame_length| is the length of the new frame. 1534 | // * |buffer_length| is the length of the buffer. 1535 | // Output: 1536 | // * |buffer| is the updated buffer. 1537 | static void UpdateBuffer(const int16_t *frame, 1538 | size_t frame_length, 1539 | size_t buffer_length, 1540 | float *buffer) { 1541 | assert(buffer_length < 2 * frame_length); 1542 | 1543 | memcpy(buffer, 1544 | buffer + frame_length, 1545 | sizeof(*buffer) * (buffer_length - frame_length)); 1546 | if (frame) { 1547 | for (int i = 0; i < frame_length; ++i) { 1548 | buffer[buffer_length - frame_length + i] = frame[i]; 1549 | } 1550 | } else { 1551 | memset(buffer + buffer_length - frame_length, 1552 | 0, 1553 | sizeof(*buffer) * frame_length); 1554 | } 1555 | } 1556 | 1557 | // Transforms the signal from time to frequency domain. 1558 | // Inputs: 1559 | // * |time_data| is the signal in the time domain. 1560 | // * |time_data_length| is the length of the analysis buffer. 1561 | // * |magnitude_length| is the length of the spectrum magnitude, which equals 1562 | // the length of both |real| and |imag| (time_data_length / 2 + 1). 1563 | // Outputs: 1564 | // * |time_data| is the signal in the frequency domain. 1565 | // * |real| is the real part of the frequency domain. 1566 | // * |imag| is the imaginary part of the frequency domain. 1567 | // * |magn| is the calculated signal magnitude in the frequency domain. 1568 | static void FFT(NoiseSuppressionC *self, 1569 | float *time_data, 1570 | size_t time_data_length, 1571 | size_t magnitude_length, 1572 | float *real, 1573 | float *imag, 1574 | float *magn) { 1575 | size_t i; 1576 | 1577 | assert(magnitude_length == time_data_length / 2 + 1); 1578 | 1579 | WebRtc_rdft(time_data_length, 1, time_data, self->ip, self->wfft); 1580 | 1581 | imag[0] = 0; 1582 | real[0] = time_data[0]; 1583 | magn[0] = fabsf(real[0]) + 1.f; 1584 | imag[magnitude_length - 1] = 0; 1585 | real[magnitude_length - 1] = time_data[1]; 1586 | magn[magnitude_length - 1] = fabsf(real[magnitude_length - 1]) + 1.f; 1587 | for (i = 1; i < magnitude_length - 1; ++i) { 1588 | real[i] = time_data[2 * i]; 1589 | imag[i] = time_data[2 * i + 1]; 1590 | // Magnitude spectrum. 1591 | magn[i] = sqrtf(real[i] * real[i] + imag[i] * imag[i]) + 1.f; 1592 | } 1593 | } 1594 | 1595 | // Transforms the signal from frequency to time domain. 1596 | // Inputs: 1597 | // * |real| is the real part of the frequency domain. 1598 | // * |imag| is the imaginary part of the frequency domain. 1599 | // * |magnitude_length| is the length of the spectrum magnitude, which equals 1600 | // the length of both |real| and |imag|. 1601 | // * |time_data_length| is the length of the analysis buffer 1602 | // (2 * (magnitude_length - 1)). 1603 | // Output: 1604 | // * |time_data| is the signal in the time domain. 1605 | static void IFFT(NoiseSuppressionC *self, 1606 | const float *real, 1607 | const float *imag, 1608 | size_t magnitude_length, 1609 | size_t time_data_length, 1610 | float *time_data) { 1611 | size_t i; 1612 | 1613 | assert(time_data_length == 2 * (magnitude_length - 1)); 1614 | 1615 | time_data[0] = real[0]; 1616 | time_data[1] = real[magnitude_length - 1]; 1617 | for (i = 1; i < magnitude_length - 1; ++i) { 1618 | time_data[2 * i] = real[i]; 1619 | time_data[2 * i + 1] = imag[i]; 1620 | } 1621 | WebRtc_rdft(time_data_length, -1, time_data, self->ip, self->wfft); 1622 | 1623 | for (i = 0; i < time_data_length; ++i) { 1624 | time_data[i] *= 2.f / time_data_length; // FFT scaling. 1625 | } 1626 | } 1627 | 1628 | // Calculates the energy of a buffer. 1629 | // Inputs: 1630 | // * |buffer| is the buffer over which the energy is calculated. 1631 | // * |length| is the length of the buffer. 1632 | // Returns the calculated energy. 1633 | static float Energy(const float *buffer, size_t length) { 1634 | size_t i; 1635 | float energy = 0.f; 1636 | 1637 | for (i = 0; i < length; ++i) { 1638 | energy += buffer[i] * buffer[i]; 1639 | } 1640 | 1641 | return energy; 1642 | } 1643 | 1644 | // Windows a buffer. 1645 | // Inputs: 1646 | // * |window| is the window by which to multiply. 1647 | // * |data| is the data without windowing. 1648 | // * |length| is the length of the window and data. 1649 | // Output: 1650 | // * |data_windowed| is the windowed data. 1651 | static void Windowing(const float *window, 1652 | const float *data, 1653 | size_t length, 1654 | float *data_windowed) { 1655 | size_t i; 1656 | 1657 | for (i = 0; i < length; ++i) { 1658 | data_windowed[i] = window[i] * data[i]; 1659 | } 1660 | } 1661 | 1662 | // Estimate prior SNR decision-directed and compute DD based Wiener Filter. 1663 | // Input: 1664 | // * |magn| is the signal magnitude spectrum estimate. 1665 | // Output: 1666 | // * |theFilter| is the frequency response of the computed Wiener filter. 1667 | static void ComputeDdBasedWienerFilter(const NoiseSuppressionC *self, 1668 | const float *magn, 1669 | float *theFilter) { 1670 | size_t i; 1671 | float snrPrior, previousEstimateStsa, currentEstimateStsa; 1672 | 1673 | for (i = 0; i < self->magnLen; i++) { 1674 | // Previous estimate: based on previous frame with gain filter. 1675 | previousEstimateStsa = self->magnPrevProcess[i] / 1676 | (self->noisePrev[i] + 0.0001f) * self->smooth[i]; 1677 | // Post and prior SNR. 1678 | currentEstimateStsa = 0.f; 1679 | if (magn[i] > self->noise[i]) { 1680 | currentEstimateStsa = magn[i] / (self->noise[i] + 0.0001f) - 1.f; 1681 | } 1682 | // DD estimate is sum of two terms: current estimate and previous estimate. 1683 | // Directed decision update of |snrPrior|. 1684 | snrPrior = DD_PR_SNR * previousEstimateStsa + 1685 | (1.f - DD_PR_SNR) * currentEstimateStsa; 1686 | // Gain filter. 1687 | theFilter[i] = snrPrior / (self->overdrive + snrPrior); 1688 | } // End of loop over frequencies. 1689 | } 1690 | 1691 | // Changes the aggressiveness of the noise suppression method. 1692 | // |mode| = 0 is mild (6dB), |mode| = 1 is medium (10dB) and |mode| = 2 is 1693 | // aggressive (15dB). 1694 | // Returns 0 on success and -1 otherwise. 1695 | int WebRtcNs_set_policy_core(NoiseSuppressionC *self, int mode) { 1696 | // Allow for modes: 0, 1, 2, 3. 1697 | if (mode == 0) { 1698 | self->overdrive = 1.f; 1699 | self->denoiseBound = 0.5f; 1700 | self->gainmap = 0; 1701 | } else if (mode == 1) { 1702 | // self->overdrive = 1.25f; 1703 | self->overdrive = 1.f; 1704 | self->denoiseBound = 0.25f; 1705 | self->gainmap = 1; 1706 | } else if (mode == 2) { 1707 | // self->overdrive = 1.25f; 1708 | self->overdrive = 1.1f; 1709 | self->denoiseBound = 0.125f; 1710 | self->gainmap = 1; 1711 | } else if (mode == 3) { 1712 | // self->overdrive = 1.3f; 1713 | self->overdrive = 1.25f; 1714 | self->denoiseBound = 0.09f; 1715 | self->gainmap = 1; 1716 | } else { 1717 | return -1; 1718 | } 1719 | self->aggrMode = mode; 1720 | return 0; 1721 | } 1722 | 1723 | void WebRtcNs_AnalyzeCore(NoiseSuppressionC *self, const int16_t *speechFrame) { 1724 | size_t i; 1725 | const size_t kStartBand = 5; // Skip first frequency bins during estimation. 1726 | int updateParsFlag; 1727 | float energy; 1728 | float signalEnergy = 0.f; 1729 | float sumMagn = 0.f; 1730 | float tmpFloat1, tmpFloat2, tmpFloat3; 1731 | float winData[ANAL_BLOCKL_MAX]; 1732 | float magn[HALF_ANAL_BLOCKL], noise[HALF_ANAL_BLOCKL]; 1733 | float snrLocPost[HALF_ANAL_BLOCKL], snrLocPrior[HALF_ANAL_BLOCKL]; 1734 | float real[ANAL_BLOCKL_MAX], imag[HALF_ANAL_BLOCKL]; 1735 | // Variables during startup. 1736 | float sum_log_i = 0.0; 1737 | float sum_log_i_square = 0.0; 1738 | float sum_log_magn = 0.0; 1739 | float sum_log_i_log_magn = 0.0; 1740 | float parametric_exp = 0.0; 1741 | float parametric_num = 0.0; 1742 | 1743 | // Check that initiation has been done. 1744 | assert(1 == self->initFlag); 1745 | updateParsFlag = self->modelUpdatePars[0]; 1746 | 1747 | // Update analysis buffer for L band. 1748 | UpdateBuffer(speechFrame, self->blockLen, self->anaLen, self->analyzeBuf); 1749 | 1750 | Windowing(self->window, self->analyzeBuf, self->anaLen, winData); 1751 | energy = Energy(winData, self->anaLen); 1752 | if (energy == 0.0) { 1753 | // We want to avoid updating statistics in this case: 1754 | // Updating feature statistics when we have zeros only will cause 1755 | // thresholds to move towards zero signal situations. This in turn has the 1756 | // effect that once the signal is "turned on" (non-zero values) everything 1757 | // will be treated as speech and there is no noise suppression effect. 1758 | // Depending on the duration of the inactive signal it takes a 1759 | // considerable amount of time for the system to learn what is noise and 1760 | // what is speech. 1761 | return; 1762 | } 1763 | 1764 | self->blockInd++; // Update the block index only when we process a block. 1765 | 1766 | FFT(self, winData, self->anaLen, self->magnLen, real, imag, magn); 1767 | 1768 | for (i = 0; i < self->magnLen; i++) { 1769 | signalEnergy += real[i] * real[i] + imag[i] * imag[i]; 1770 | sumMagn += magn[i]; 1771 | if (self->blockInd < END_STARTUP_SHORT) { 1772 | if (i >= kStartBand) { 1773 | tmpFloat2 = logf((float) i); 1774 | sum_log_i += tmpFloat2; 1775 | sum_log_i_square += tmpFloat2 * tmpFloat2; 1776 | tmpFloat1 = logf(magn[i]); 1777 | sum_log_magn += tmpFloat1; 1778 | sum_log_i_log_magn += tmpFloat2 * tmpFloat1; 1779 | } 1780 | } 1781 | } 1782 | signalEnergy /= self->magnLen; 1783 | self->signalEnergy = signalEnergy; 1784 | self->sumMagn = sumMagn; 1785 | 1786 | // Quantile noise estimate. 1787 | NoiseEstimation(self, magn, noise); 1788 | // Compute simplified noise model during startup. 1789 | if (self->blockInd < END_STARTUP_SHORT) { 1790 | // Estimate White noise. 1791 | self->whiteNoiseLevel += sumMagn / self->magnLen * self->overdrive; 1792 | // Estimate Pink noise parameters. 1793 | tmpFloat1 = sum_log_i_square * (self->magnLen - kStartBand); 1794 | tmpFloat1 -= (sum_log_i * sum_log_i); 1795 | tmpFloat2 = 1796 | (sum_log_i_square * sum_log_magn - sum_log_i * sum_log_i_log_magn); 1797 | tmpFloat3 = tmpFloat2 / tmpFloat1; 1798 | // Constrain the estimated spectrum to be positive. 1799 | if (tmpFloat3 < 0.f) { 1800 | tmpFloat3 = 0.f; 1801 | } 1802 | self->pinkNoiseNumerator += tmpFloat3; 1803 | tmpFloat2 = (sum_log_i * sum_log_magn); 1804 | tmpFloat2 -= (self->magnLen - kStartBand) * sum_log_i_log_magn; 1805 | tmpFloat3 = tmpFloat2 / tmpFloat1; 1806 | // Constrain the pink noise power to be in the interval [0, 1]. 1807 | if (tmpFloat3 < 0.f) { 1808 | tmpFloat3 = 0.f; 1809 | } 1810 | if (tmpFloat3 > 1.f) { 1811 | tmpFloat3 = 1.f; 1812 | } 1813 | self->pinkNoiseExp += tmpFloat3; 1814 | 1815 | // Calculate frequency independent parts of parametric noise estimate. 1816 | if (self->pinkNoiseExp > 0.f) { 1817 | // Use pink noise estimate. 1818 | parametric_num = 1819 | expf(self->pinkNoiseNumerator / (float) (self->blockInd + 1)); 1820 | parametric_num *= (float) (self->blockInd + 1); 1821 | parametric_exp = self->pinkNoiseExp / (float) (self->blockInd + 1); 1822 | } 1823 | for (i = 0; i < self->magnLen; i++) { 1824 | // Estimate the background noise using the white and pink noise 1825 | // parameters. 1826 | if (self->pinkNoiseExp == 0.f) { 1827 | // Use white noise estimate. 1828 | self->parametricNoise[i] = self->whiteNoiseLevel; 1829 | } else { 1830 | // Use pink noise estimate. 1831 | float use_band = (float) (i < kStartBand ? kStartBand : i); 1832 | self->parametricNoise[i] = 1833 | parametric_num / powf(use_band, parametric_exp); 1834 | } 1835 | // Weight quantile noise with modeled noise. 1836 | noise[i] *= (self->blockInd); 1837 | tmpFloat2 = 1838 | self->parametricNoise[i] * (END_STARTUP_SHORT - self->blockInd); 1839 | noise[i] += (tmpFloat2 / (float) (self->blockInd + 1)); 1840 | noise[i] /= END_STARTUP_SHORT; 1841 | } 1842 | } 1843 | // Compute average signal during END_STARTUP_LONG time: 1844 | // used to normalize spectral difference measure. 1845 | if (self->blockInd < END_STARTUP_LONG) { 1846 | self->featureData[5] *= self->blockInd; 1847 | self->featureData[5] += signalEnergy; 1848 | self->featureData[5] /= (self->blockInd + 1); 1849 | } 1850 | 1851 | // Post and prior SNR needed for SpeechNoiseProb. 1852 | ComputeSnr(self, magn, noise, snrLocPrior, snrLocPost); 1853 | 1854 | FeatureUpdate(self, magn, updateParsFlag); 1855 | SpeechNoiseProb(self, self->speechProb, snrLocPrior, snrLocPost); 1856 | UpdateNoiseEstimate(self, magn, noise); 1857 | 1858 | // Keep track of noise spectrum for next frame. 1859 | memcpy(self->noise, noise, sizeof(*noise) * self->magnLen); 1860 | memcpy(self->magnPrevAnalyze, magn, sizeof(*magn) * self->magnLen); 1861 | } 1862 | 1863 | void WebRtcNs_ProcessCore(NoiseSuppressionC *self, 1864 | const int16_t *const *speechFrame, 1865 | size_t num_bands, 1866 | int16_t *const *outFrame) { 1867 | // Main routine for noise reduction. 1868 | int flagHB = 0; 1869 | size_t i, j; 1870 | 1871 | float energy1, energy2, gain, factor, factor1, factor2; 1872 | float fout[BLOCKL_MAX]; 1873 | float winData[ANAL_BLOCKL_MAX]; 1874 | float magn[HALF_ANAL_BLOCKL]; 1875 | float theFilter[HALF_ANAL_BLOCKL], theFilterTmp[HALF_ANAL_BLOCKL]; 1876 | float real[ANAL_BLOCKL_MAX], imag[HALF_ANAL_BLOCKL]; 1877 | 1878 | // SWB variables. 1879 | int deltaBweHB = 1; 1880 | int deltaGainHB = 1; 1881 | float decayBweHB = 1.0; 1882 | float gainMapParHB = 1.0; 1883 | float avgProbSpeechHB, avgProbSpeechHBTmp, avgFilterGainHB, gainModHB; 1884 | float sumMagnAnalyze, sumMagnProcess; 1885 | 1886 | // Check that initiation has been done. 1887 | assert(1 == self->initFlag); 1888 | assert(num_bands - 1 <= NUM_HIGH_BANDS_MAX); 1889 | 1890 | const int16_t *const *speechFrameHB = NULL; 1891 | int16_t *const *outFrameHB = NULL; 1892 | size_t num_high_bands = 0; 1893 | if (num_bands > 1) { 1894 | speechFrameHB = &speechFrame[1]; 1895 | outFrameHB = &outFrame[1]; 1896 | num_high_bands = num_bands - 1; 1897 | flagHB = 1; 1898 | // Range for averaging low band quantities for H band gain. 1899 | deltaBweHB = (int) self->magnLen / 4; 1900 | deltaGainHB = deltaBweHB; 1901 | } 1902 | 1903 | // Update analysis buffer for L band. 1904 | UpdateBuffer(speechFrame[0], self->blockLen, self->anaLen, self->dataBuf); 1905 | 1906 | if (flagHB == 1) { 1907 | // Update analysis buffer for H bands. 1908 | for (i = 0; i < num_high_bands; ++i) { 1909 | UpdateBuffer(speechFrameHB[i], 1910 | self->blockLen, 1911 | self->anaLen, 1912 | self->dataBufHB[i]); 1913 | } 1914 | } 1915 | 1916 | Windowing(self->window, self->dataBuf, self->anaLen, winData); 1917 | energy1 = Energy(winData, self->anaLen); 1918 | if (energy1 == 0.0) { 1919 | // Synthesize the special case of zero input. 1920 | // Read out fully processed segment. 1921 | for (i = self->windShift; i < self->blockLen + self->windShift; i++) { 1922 | fout[i - self->windShift] = self->syntBuf[i]; 1923 | } 1924 | // Update synthesis buffer. 1925 | UpdateBuffer(NULL, self->blockLen, self->anaLen, self->syntBuf); 1926 | 1927 | for (i = 0; i < self->blockLen; ++i) 1928 | outFrame[0][i] = 1929 | SPL_SAT(32767, fout[i], (-32768)); 1930 | 1931 | // For time-domain gain of HB. 1932 | if (flagHB == 1) { 1933 | for (i = 0; i < num_high_bands; ++i) { 1934 | for (j = 0; j < self->blockLen; ++j) { 1935 | outFrameHB[i][j] = SPL_SAT(32767, 1936 | self->dataBufHB[i][j], 1937 | (-32768)); 1938 | } 1939 | } 1940 | } 1941 | 1942 | return; 1943 | } 1944 | 1945 | FFT(self, winData, self->anaLen, self->magnLen, real, imag, magn); 1946 | 1947 | if (self->blockInd < END_STARTUP_SHORT) { 1948 | for (i = 0; i < self->magnLen; i++) { 1949 | self->initMagnEst[i] += magn[i]; 1950 | } 1951 | } 1952 | 1953 | ComputeDdBasedWienerFilter(self, magn, theFilter); 1954 | 1955 | for (i = 0; i < self->magnLen; i++) { 1956 | // Flooring bottom. 1957 | if (theFilter[i] < self->denoiseBound) { 1958 | theFilter[i] = self->denoiseBound; 1959 | } 1960 | // Flooring top. 1961 | if (theFilter[i] > 1.f) { 1962 | theFilter[i] = 1.f; 1963 | } 1964 | if (self->blockInd < END_STARTUP_SHORT) { 1965 | theFilterTmp[i] = 1966 | (self->initMagnEst[i] - self->overdrive * self->parametricNoise[i]); 1967 | theFilterTmp[i] /= (self->initMagnEst[i] + 0.0001f); 1968 | // Flooring bottom. 1969 | if (theFilterTmp[i] < self->denoiseBound) { 1970 | theFilterTmp[i] = self->denoiseBound; 1971 | } 1972 | // Flooring top. 1973 | if (theFilterTmp[i] > 1.f) { 1974 | theFilterTmp[i] = 1.f; 1975 | } 1976 | // Weight the two suppression filters. 1977 | theFilter[i] *= (self->blockInd); 1978 | theFilterTmp[i] *= (END_STARTUP_SHORT - self->blockInd); 1979 | theFilter[i] += theFilterTmp[i]; 1980 | theFilter[i] /= (END_STARTUP_SHORT); 1981 | } 1982 | 1983 | self->smooth[i] = theFilter[i]; 1984 | real[i] *= self->smooth[i]; 1985 | imag[i] *= self->smooth[i]; 1986 | } 1987 | // Keep track of |magn| spectrum for next frame. 1988 | memcpy(self->magnPrevProcess, magn, sizeof(*magn) * self->magnLen); 1989 | memcpy(self->noisePrev, self->noise, sizeof(self->noise[0]) * self->magnLen); 1990 | // Back to time domain. 1991 | IFFT(self, real, imag, self->magnLen, self->anaLen, winData); 1992 | 1993 | // Scale factor: only do it after END_STARTUP_LONG time. 1994 | factor = 1.f; 1995 | if (self->gainmap == 1 && self->blockInd > END_STARTUP_LONG) { 1996 | factor1 = 1.f; 1997 | factor2 = 1.f; 1998 | energy2 = Energy(winData, self->anaLen); 1999 | gain = sqrtf(energy2 / (energy1 + 1.f)); 2000 | 2001 | // Scaling for new version. 2002 | if (gain > B_LIM) { 2003 | factor1 = 1.f + 1.3f * (gain - B_LIM); 2004 | if (gain * factor1 > 1.f) { 2005 | factor1 = 1.f / gain; 2006 | } 2007 | } 2008 | if (gain < B_LIM) { 2009 | // Don't reduce scale too much for pause regions: 2010 | // attenuation here should be controlled by flooring. 2011 | if (gain <= self->denoiseBound) { 2012 | gain = self->denoiseBound; 2013 | } 2014 | factor2 = 1.f - 0.3f * (B_LIM - gain); 2015 | } 2016 | // Combine both scales with speech/noise prob: 2017 | // note prior (priorSpeechProb) is not frequency dependent. 2018 | factor = self->priorSpeechProb * factor1 + 2019 | (1.f - self->priorSpeechProb) * factor2; 2020 | } // Out of self->gainmap == 1. 2021 | 2022 | Windowing(self->window, winData, self->anaLen, winData); 2023 | 2024 | // Synthesis. 2025 | for (i = 0; i < self->anaLen; i++) { 2026 | self->syntBuf[i] += factor * winData[i]; 2027 | } 2028 | // Read out fully processed segment. 2029 | for (i = self->windShift; i < self->blockLen + self->windShift; i++) { 2030 | fout[i - self->windShift] = self->syntBuf[i]; 2031 | } 2032 | // Update synthesis buffer. 2033 | UpdateBuffer(NULL, self->blockLen, self->anaLen, self->syntBuf); 2034 | 2035 | for (i = 0; i < self->blockLen; ++i) 2036 | outFrame[0][i] = 2037 | SPL_SAT(32767, fout[i], (-32768)); 2038 | 2039 | // For time-domain gain of HB. 2040 | if (flagHB == 1) { 2041 | // Average speech prob from low band. 2042 | // Average over second half (i.e., 4->8kHz) of frequencies spectrum. 2043 | avgProbSpeechHB = 0.0; 2044 | for (i = self->magnLen - deltaBweHB - 1; i < self->magnLen - 1; i++) { 2045 | avgProbSpeechHB += self->speechProb[i]; 2046 | } 2047 | avgProbSpeechHB = avgProbSpeechHB / ((float) deltaBweHB); 2048 | // If the speech was suppressed by a component between Analyze and 2049 | // Process, for example the AEC, then it should not be considered speech 2050 | // for high band suppression purposes. 2051 | sumMagnAnalyze = 0; 2052 | sumMagnProcess = 0; 2053 | for (i = 0; i < self->magnLen; ++i) { 2054 | sumMagnAnalyze += self->magnPrevAnalyze[i]; 2055 | sumMagnProcess += self->magnPrevProcess[i]; 2056 | } 2057 | avgProbSpeechHB *= sumMagnProcess / sumMagnAnalyze; 2058 | // Average filter gain from low band. 2059 | // Average over second half (i.e., 4->8kHz) of frequencies spectrum. 2060 | avgFilterGainHB = 0.0; 2061 | for (i = self->magnLen - deltaGainHB - 1; i < self->magnLen - 1; i++) { 2062 | avgFilterGainHB += self->smooth[i]; 2063 | } 2064 | avgFilterGainHB = avgFilterGainHB / ((float) (deltaGainHB)); 2065 | avgProbSpeechHBTmp = 2.f * avgProbSpeechHB - 1.f; 2066 | // Gain based on speech probability. 2067 | gainModHB = 0.5f * (1.f + tanhf(gainMapParHB * avgProbSpeechHBTmp)); 2068 | // Combine gain with low band gain. 2069 | float gainTimeDomainHB = 0.5f * gainModHB + 0.5f * avgFilterGainHB; 2070 | if (avgProbSpeechHB >= 0.5f) { 2071 | gainTimeDomainHB = 0.25f * gainModHB + 0.75f * avgFilterGainHB; 2072 | } 2073 | gainTimeDomainHB = gainTimeDomainHB * decayBweHB; 2074 | // Make sure gain is within flooring range. 2075 | // Flooring bottom. 2076 | if (gainTimeDomainHB < self->denoiseBound) { 2077 | gainTimeDomainHB = self->denoiseBound; 2078 | } 2079 | // Flooring top. 2080 | if (gainTimeDomainHB > 1.f) { 2081 | gainTimeDomainHB = 1.f; 2082 | } 2083 | // Apply gain. 2084 | for (i = 0; i < num_high_bands; ++i) { 2085 | for (j = 0; j < self->blockLen; j++) { 2086 | outFrameHB[i][j] = 2087 | SPL_SAT(32767, 2088 | gainTimeDomainHB * self->dataBufHB[i][j], 2089 | (-32768)); 2090 | } 2091 | } 2092 | } // End of H band gain computation. 2093 | } 2094 | 2095 | NsHandle *WebRtcNs_Create() { 2096 | NoiseSuppressionC *self = (NoiseSuppressionC *) malloc(sizeof(NoiseSuppressionC)); 2097 | if (self != NULL) { 2098 | self->initFlag = 0; 2099 | } 2100 | return (NsHandle *) self; 2101 | } 2102 | 2103 | void WebRtcNs_Free(NsHandle *NS_inst) { 2104 | free(NS_inst); 2105 | } 2106 | 2107 | int WebRtcNs_Init(NsHandle *NS_inst, uint32_t fs) { 2108 | return WebRtcNs_InitCore((NoiseSuppressionC *) NS_inst, fs); 2109 | } 2110 | 2111 | int WebRtcNs_set_policy(NsHandle *NS_inst, int mode) { 2112 | return WebRtcNs_set_policy_core((NoiseSuppressionC *) NS_inst, mode); 2113 | } 2114 | 2115 | void WebRtcNs_Analyze(NsHandle *NS_inst, const int16_t *spframe) { 2116 | WebRtcNs_AnalyzeCore((NoiseSuppressionC *) NS_inst, spframe); 2117 | } 2118 | 2119 | void WebRtcNs_Process(NsHandle *NS_inst, 2120 | const int16_t *const *spframe, 2121 | size_t num_bands, 2122 | int16_t *const *outframe) { 2123 | WebRtcNs_ProcessCore((NoiseSuppressionC *) NS_inst, spframe, num_bands, 2124 | outframe); 2125 | } 2126 | 2127 | float WebRtcNs_prior_speech_probability(NsHandle *handle) { 2128 | NoiseSuppressionC *self = (NoiseSuppressionC *) handle; 2129 | if (handle == NULL) { 2130 | return -1; 2131 | } 2132 | if (self->initFlag == 0) { 2133 | return -1; 2134 | } 2135 | return self->priorSpeechProb; 2136 | } 2137 | 2138 | const float *WebRtcNs_noise_estimate(const NsHandle *handle) { 2139 | const NoiseSuppressionC *self = (const NoiseSuppressionC *) handle; 2140 | if (handle == NULL || self->initFlag == 0) { 2141 | return NULL; 2142 | } 2143 | return self->noise; 2144 | } 2145 | 2146 | size_t WebRtcNs_num_freq() { 2147 | return HALF_ANAL_BLOCKL; 2148 | } 2149 | --------------------------------------------------------------------------------