關(guān)于實(shí)現(xiàn)唱吧清唱功能的理解

如果圖片不顯示可以到我的小站去看

簡介

AVFoundation

在iOS上多媒體的處理主要依賴的是AVFoundation框架,而AVFoundation是基于CoreAudio、CoreVideo、CoreMedia、CoreAnimation之上高層框架,在AVFoundation框架之上蘋果還提供給我們更高層一些處理媒體數(shù)據(jù)的框架。

image

如AVKit、iOS的UIKit、OS的AppKit。AVFoundation提供了大量強(qiáng)大的工具集,可通過這個(gè)框架處理音視頻編程,但是如同蘋果中的的Kit一樣,封裝的越高級,個(gè)性化就會困難些,一些實(shí)際項(xiàng)目中的奇葩需求難以實(shí)現(xiàn)。本章所講的內(nèi)容是AVFoundation上層加下層的AVAudioEngine實(shí)現(xiàn)。

AVAudioEngine

AVAudioEngine是Objective-C的音頻API接口,具有低延遲(low-latency)和實(shí)時(shí)(real-time)的音頻功能,并且具有如下特點(diǎn):

  • 讀寫所有Core Audio支持的格式音頻文件

  • 播放和錄音使用 (files) 和音頻緩沖區(qū) (buffers)

  • 動態(tài)配置音頻處理模塊 (audio processing blocks)

  • 可以進(jìn)行音頻挖掘處理 (tap processing)

  • 可以進(jìn)行立體聲音頻信號混合和3d效果的混合

  • 音樂設(shè)備數(shù)字接口MIDI 回放和控制,通過樂器的采樣器

AVAudioEngine的工作原理可以簡單的分為三個(gè)部分:

image

從圖中可以看出AVAudioEngine的每一步操作都是一個(gè)音頻操作節(jié)點(diǎn)(Node),每個(gè)完整的操作都包含輸入節(jié)點(diǎn)和輸出節(jié)點(diǎn)以及經(jīng)中間的若干個(gè)處理節(jié)點(diǎn),包括但不限于,添加音效、混音、音頻處理等。整體的流程和GPUImage的流程差不多,都是鏈?zhǔn)浇Y(jié)構(gòu),通過節(jié)點(diǎn)來鏈接成一個(gè)完整的流水線,其中每個(gè)節(jié)點(diǎn)都有自己特有的屬性,可以通過改變屬性的值來改變經(jīng)由該節(jié)點(diǎn)后的音頻輸出效果,用音效節(jié)點(diǎn)舉例:一個(gè)聲音流通過這個(gè)音效節(jié)點(diǎn),假如這個(gè)節(jié)點(diǎn)可以給該段聲音添加一個(gè)回響的效果,那么通過該節(jié)點(diǎn)特有的屬性可以設(shè)置回想的間隔、干濕程度等,這樣一來經(jīng)過這個(gè)節(jié)點(diǎn)處理過的聲音流就會變成我們想要的樣子,然后他作為為一個(gè)輸入了再次流入其他節(jié)點(diǎn)。上圖的Mixer其實(shí)是包含若干個(gè)這樣的音效節(jié)點(diǎn)

image

原理

清唱的功能很簡單,就是通過麥克風(fēng)錄制聲音,然后添加音效或者做一些處理之后再輸出,因?yàn)椴灰錁罚允÷粤艘淮蟛糠植僮?添加配樂完整K歌在下期會講到),但是有一個(gè)問題就是耳返,也叫返送:

image

這個(gè)東西是必不可少的,因?yàn)橛辛硕的憔涂梢詫?shí)時(shí)調(diào)整自己的聲音,極大的降低了走調(diào)的風(fēng)險(xiǎn)和尷尬,一個(gè)很簡單的例子,現(xiàn)在有不少人喜歡在水房唱歌或者是洗澡的時(shí)候唱歌,原因就是在水房或者是衛(wèi)生間通常會有回音,而回音就是天然的耳返,所以在有回音的地方唱歌就會感覺自己的聲音洪亮而且音準(zhǔn)很好(因?yàn)槟憧梢詫?shí)時(shí)的通過回音來調(diào)整自己的聲調(diào))。演唱會上唱歌的人的耳機(jī)中都是耳返。而且耳返要有一個(gè)要求就是,你所聽到的你自己的聲音一定要和觀眾或者是其他的人聽到的一樣,不然就不會有作用,我們平時(shí)自己說話自己能聽到是因?yàn)槁曇敉ㄟ^骨傳導(dǎo)到達(dá)我們的耳朵,而聽眾聽到的是通過空氣介質(zhì)傳播,所以是否有耳返直接決定了你演唱質(zhì)量的好壞。

使用AVAudioEngine來完成這個(gè)功能其實(shí)就是運(yùn)用了他的實(shí)時(shí)音頻的特點(diǎn),他可以幾乎在沒有延遲的情況下同時(shí)創(chuàng)建音頻的輸入和輸出,而且對這個(gè)做了高度的封裝使我們能更加關(guān)心音效調(diào)整

實(shí)現(xiàn)

創(chuàng)建音頻文件用來接收待錄制的聲音:
//創(chuàng)建音頻文件。
   NSString * path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
   NSString * filePath = [path stringByAppendingPathComponent:@"123.caf"];
   NSURL * url = [NSURL fileURLWithPath:filePath];
創(chuàng)建AVAudioEngine,并打通輸入和輸出節(jié)點(diǎn):
  • 創(chuàng)建AVAudioEngine,并初始化。這里要弄成屬性不然會被釋放,沒有效果

    @interface ViewController (){
    
    @property (nonatomic, strong) AVAudioEngine * engine;
    @property (nonatomic, strong) AVAudioMixerNode * mixer;
    @end
    
    
    self.engine = [[AVAudioEngine alloc] init];
    self.mixer = [[AVAudioMixerNode alloc] init];
    
  • 打通輸入和輸出節(jié)點(diǎn):

    [_engine connect:_engine.inputNode to:_engine.outputNode format:[_engine.inputNode inputFormatForBus:AVAudioPlayerNodeBufferLoops]];
    
    

    所使用的是如下方法。

    /*!   @method connect:to:format:
      @abstract
          Establish a connection between two nodes
      @discussion
          This calls connect:to:fromBus:toBus:format: using bus 0 on the source node,
          and bus 0 on the destination node, except in the case of a destination which is a mixer,
          in which case the destination is the mixer's nextAvailableInputBus.
    */
    - (void)connect:(AVAudioNode *)node1 to:(AVAudioNode *)node2 format:(AVAudioFormat * __nullable)format;
    
  • 開啟AVAudioEngine:

    該方法可能會開啟失敗,需要開發(fā)者自定去處理

    [_engine startAndReturnError:nil];
    
    

    以上步驟走完后并且開啟成功你就會發(fā)現(xiàn)你從耳機(jī)里面可以實(shí)時(shí)的聽到你的聲音了。

  • 音效:

    正常來說光有耳返還不夠,因?yàn)榍宄m然沒有配樂伴奏,但是是支持用戶調(diào)節(jié)音效的,類似于變聲。這就用到AVAudioEngine中的AVAudioUnitEffect類。

    image
    • 1.AVAudioUnitReverb:混響,混響可以模擬咱們在一個(gè)空曠的環(huán)境,比如教堂、大房間等,這樣咱們在說話的時(shí)候,就會有回音,并且聲音也比較有立體感。其中該類別下面又分為
    typedef NS_ENUM(NSInteger, AVAudioUnitReverbPreset) {
      AVAudioUnitReverbPresetSmallRoom       = 0,
      AVAudioUnitReverbPresetMediumRoom      = 1,
      AVAudioUnitReverbPresetLargeRoom       = 2,
      AVAudioUnitReverbPresetMediumHall      = 3,
      AVAudioUnitReverbPresetLargeHall       = 4,
      AVAudioUnitReverbPresetPlate           = 5,
      AVAudioUnitReverbPresetMediumChamber   = 6,
      AVAudioUnitReverbPresetLargeChamber    = 7,
      AVAudioUnitReverbPresetCathedral       = 8,
      AVAudioUnitReverbPresetLargeRoom2      = 9,
      AVAudioUnitReverbPresetMediumHall2     = 10,
      AVAudioUnitReverbPresetMediumHall3     = 11,
      AVAudioUnitReverbPresetLargeHall2      = 12
      } NS_ENUM_AVAILABLE(10_10, 8_0);
    

    從名字可以看出是在模擬不同環(huán)境下的音效,比如其中的大中小屋子,大廳等。

    該類別可以自定義的屬性是wetDryMix,就是可以讓我們的聲音更空靈。

      /*! @property wetDryMix
        @abstract
        Blend of the wet and dry signals
        Range:      0 (all dry) -> 100 (all wet)
        Unit:       Percent
      */
    @property (nonatomic) float wetDryMix;
    

    可以通過如下方式創(chuàng)建AVAudioUnitReverb

    AVAudioUnitReverb * reverd = [[AVAudioUnitReverb alloc] init];
    reverd.wetDryMix = 100;
    [reverd loadFactoryPreset:AVAudioUnitReverbPresetLargeRoom];
    
    • 2.AVAudioUnitEQ:均衡器,咱們可以使用均衡器來調(diào)節(jié)咱們音頻的各個(gè)頻段,比如,我想讓我的低音更加渾厚,我就可以調(diào)節(jié)EQ的20-150HZ的頻段,如果你想讓你的聲音更加明亮,那可以調(diào)節(jié)500-1KHZ的頻段,這個(gè)調(diào)節(jié)涉及到一些專業(yè)方面的知識,如果只是想讓用戶去使用的話,可以用蘋果給我們更封裝好的幾個(gè)效果即可,這個(gè)就類似于photoshop和美圖秀秀的區(qū)別。

      typedef NS_ENUM(NSInteger, AVAudioUnitEQFilterType) {
        AVAudioUnitEQFilterTypeParametric        = 0,
        AVAudioUnitEQFilterTypeLowPass           = 1,
        AVAudioUnitEQFilterTypeHighPass          = 2,
        AVAudioUnitEQFilterTypeResonantLowPass   = 3,
        AVAudioUnitEQFilterTypeResonantHighPass  = 4,
        AVAudioUnitEQFilterTypeBandPass          = 5,
        AVAudioUnitEQFilterTypeBandStop          = 6,
        AVAudioUnitEQFilterTypeLowShelf          = 7,
        AVAudioUnitEQFilterTypeHighShelf         = 8,
        AVAudioUnitEQFilterTypeResonantLowShelf  = 9,
        AVAudioUnitEQFilterTypeResonantHighShelf = 10,
        } NS_ENUM_AVAILABLE(10_10, 8_0);
      

      上面是一些蘋果幫助我們定義好的濾波器,比如低通濾波器 衰弱高頻、可以引發(fā)共鳴的 低通濾波器
      不過一般在清唱的時(shí)候這個(gè)用處不大,這個(gè)效果主要用到在配合伴奏的時(shí)候,如果伴奏音調(diào)過高,可以使用該方法適當(dāng)?shù)奶岣呷寺曇粽{(diào)或者降低伴奏的音調(diào),

      可以通過如下方式使用,然后更改這個(gè)節(jié)點(diǎn)一些屬性值。

      AVAudioUnitEQ * eq = [[AVAudioUnitEQ alloc] initWithNumberOfBands:1];
      AVAudioUnitEQFilterParameters * filter = eq.bands.firstObject;
      filter.filterType = AVAudioUnitEQFilterTypeResonantHighShelf;
      filter.bandwidth = 10;
      filter.gain = 20;
      
    • 3.AVAudioUnitDistortion:失真,這個(gè)就是我們常說的電音,一般說唱或者搖滾,重金屬之類的曲風(fēng)會用到這個(gè)效果,同樣蘋果給我們提供了預(yù)設(shè)的幾個(gè)效果,如果不是有專業(yè)的需求我們可以直接使用。

      typedef NS_ENUM(NSInteger, AVAudioUnitDistortionPreset) {
        AVAudioUnitDistortionPresetDrumsBitBrush           = 0,
        AVAudioUnitDistortionPresetDrumsBufferBeats        = 1,
        AVAudioUnitDistortionPresetDrumsLoFi               = 2,
        AVAudioUnitDistortionPresetMultiBrokenSpeaker      = 3,
        AVAudioUnitDistortionPresetMultiCellphoneConcert   = 4,
        AVAudioUnitDistortionPresetMultiDecimated1         = 5,
        AVAudioUnitDistortionPresetMultiDecimated2         = 6,
        AVAudioUnitDistortionPresetMultiDecimated3         = 7,
        AVAudioUnitDistortionPresetMultiDecimated4         = 8,
        AVAudioUnitDistortionPresetMultiDistortedFunk      = 9,
        AVAudioUnitDistortionPresetMultiDistortedCubed     = 10,
        AVAudioUnitDistortionPresetMultiDistortedSquared   = 11,
        AVAudioUnitDistortionPresetMultiEcho1              = 12,
        AVAudioUnitDistortionPresetMultiEcho2              = 13,
        AVAudioUnitDistortionPresetMultiEchoTight1         = 14,
        AVAudioUnitDistortionPresetMultiEchoTight2         = 15,
        AVAudioUnitDistortionPresetMultiEverythingIsBroken = 16,
        AVAudioUnitDistortionPresetSpeechAlienChatter      = 17,
        AVAudioUnitDistortionPresetSpeechCosmicInterference = 18,
        AVAudioUnitDistortionPresetSpeechGoldenPi          = 19,
        AVAudioUnitDistortionPresetSpeechRadioTower        = 20,
        AVAudioUnitDistortionPresetSpeechWaves             = 21
      

    } NS_ENUM_AVAILABLE(10_10, 8_0);

    其實(shí)里面有些還是比較有感覺的,比如扭曲的立方體,或者外星人的喋喋不休等。有興趣的可以說都試試
    
    使用方式同之前的效果一樣
    
    

    AVAudioUnitDistortion * dist = [[AVAudioUnitDistortion alloc] init];
    [dist loadFactoryPreset:AVAudioUnitDistortionPresetDrumsBitBrush];
    dist.preGain = 4;
    dist.wetDryMix = 100;

    
    * 4.AVAudioUnitDelay:延遲,延遲就是 發(fā)出一個(gè)聲音之后,過段時(shí)間再次發(fā)出,一直衰減到聽不見。類似咱們的回聲。可以通過里面的屬性去細(xì)微的調(diào)節(jié)延遲的時(shí)間、速度等。
    
    
    
  • 添加音效:
    主要流程就是鏈?zhǔn)疥P(guān)系

    input(Mic或者音頻文件) ->效果器->output

    如果是多個(gè)音效

    input(Mic或者音頻文件) ->效果器1->效果器2->output

    我們以AVAudioUnitReverb效果為例

    AVAudioUnitReverb * reverb = [[AVAudioUnitReverb alloc] init];
    [reverb loadFactoryPreset:AVAudioUnitReverbPresetLargeRoom];
    reverb.wetDryMix = 100;
    //把混響附著到音頻引擎
    [_engine attachNode:reverb];
    //依次鏈接輸入-> 混響 -> 輸出
    [_engine connect:_engine.inputNode to:reverb format:[_engine.inputNode inputFormatForBus:AVAudioPlayerNodeBufferLoops]];
    [_engine connect:reverb to:_engine.outputNode format:[_engine.inputNode inputFormatForBus:AVAudioPlayerNodeBufferLoops]];
    //啟動引擎
    [_engine startAndReturnError:nil];
    
    

    同理添加多個(gè)音效則需要嚴(yán)格按照 input(Mic或者音頻文件) ->效果器1->效果器2->output 順序來添加

    綜上:完成了以上所有操作后你就可以實(shí)時(shí)在耳機(jī)中聽到自己經(jīng)過音效處理過的聲音了,而且這樣帶著耳機(jī)唱歌效果會非常好,聲音洪亮不易跑調(diào)。還可以針對不同的曲風(fēng)調(diào)整自己的音效。

聲音混合、寫入本地:

我們需要把我們清唱的歌曲錄制到本地,正常的錄制時(shí)使用AVAudioRecorder來進(jìn)行錄制的,像這樣

AVAudioSession * session = [AVAudioSession sharedInstance];
    [session setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
    [session setActive:YES error:nil];


    NSString * path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
    self.filePath = [path stringByAppendingPathComponent:@"SoWeak"];
    self.recordFileUrl = [NSURL fileURLWithPath:self.filePath];

    //設(shè)置參數(shù)
    NSDictionary *recordSetting = [[NSDictionary alloc] initWithObjectsAndKeys:
                                   //采樣率  8000/11025/22050/44100/96000(影響音頻的質(zhì)量)
                                   [NSNumber numberWithFloat: 8000.0],AVSampleRateKey,
                                   // 音頻格式
                                   [NSNumber numberWithInt: kAudioFormatLinearPCM],AVFormatIDKey,
                                   //采樣位數(shù)  8、16、24、32 默認(rèn)為16
                                   [NSNumber numberWithInt:16],AVLinearPCMBitDepthKey,
                                   // 音頻通道數(shù) 1 或 2
                                   [NSNumber numberWithInt: 2], AVNumberOfChannelsKey,
                                   //錄音質(zhì)量
                                   [NSNumber numberWithInt:AVAudioQualityHigh],AVEncoderAudioQualityKey,
                                   nil];
    self.recorder = [[AVAudioRecorder alloc] initWithURL:self.recordFileUrl settings:recordSetting error:nil];

    if (self.recorder) {
        _recorder.meteringEnabled = YES;
        [_recorder prepareToRecord];
        [_recorder record];
    }

但是很明顯這樣錄制聲音需要開啟session 而聲音的session是一個(gè)單利,如果這樣開啟了那么我們后面就不能用AVAudioEngine來進(jìn)行音頻采集了,也就沒有之前的效果。所有根據(jù)以往的經(jīng)驗(yàn),AVAudioEngine在開啟引擎之后一定會有一個(gè)delegate或者是block回調(diào)出采集到的數(shù)據(jù)的。于是我們找到了AudioNode中的這個(gè)方法:

- (void)installTapOnBus:(AVAudioNodeBus)bus bufferSize:(AVAudioFrameCount)bufferSize format:(AVAudioFormat * __nullable)format block:(AVAudioNodeTapBlock)tapBlock;

其中的block的buffer 便是我們采集到的數(shù)據(jù)。

/*! @typedef AVAudioNodeTapBlock
    @abstract A block that receives copies of the output of an AVAudioNode.
    @param buffer
        a buffer of audio captured from the output of an AVAudioNode
    @param when
        the time at which the buffer was captured
    @discussion
        CAUTION: This callback may be invoked on a thread other than the main thread.
*/
typedef void (^AVAudioNodeTapBlock)(AVAudioPCMBuffer *buffer, AVAudioTime *when);

我們需要把buffer轉(zhuǎn)成AVAudioFile然后通過AVAudioFile的write方法寫入

  初始化AVAudioFile
  AVAudioFile * audioFile = [[AVAudioFile alloc] initForWriting:url settings:@{} error:nil];
  然后在block中實(shí)現(xiàn)
  [audioFile writeFromBuffer:buffer error:nil];

這個(gè)時(shí)候?qū)懭氤晒θ缓蟛シ疟镜劁浺粑募l(fā)現(xiàn)只有自己的原生,并沒有后面添加的音效,回音等效果。

其實(shí)是因?yàn)槲覀冸m然添加了音效但是我們沒有把音效和原生混合在一起,即使我們實(shí)時(shí)聽到的是沒有問題的,但是當(dāng)保存到本地之后如果沒有做混合,系統(tǒng)會默認(rèn)將最原始的聲音寫入本地,這里我們需要用到

AVAudioMixerNode

他是繼承與AVAudioNode 也屬于一個(gè)特殊音頻處理節(jié)點(diǎn),使用方式和之前的音效節(jié)點(diǎn)一樣,添加在所有的處理之后、輸出之前即可,像這樣

input(Mic或者音頻文件) ->效果器1->效果器2->Mixer->output

不過唯一需要注意的是這個(gè)mixer最好也寫成屬性、不然會出問題。

所以一個(gè)完整的帶音效的清唱錄制為:

//創(chuàng)建音頻文件。
    NSString * path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
    NSString * filePath = [path stringByAppendingPathComponent:@"123.caf"];
    NSURL * url = [NSURL fileURLWithPath:filePath];
    AVAudioFile * audioFile = [[AVAudioFile alloc] initForWriting:url settings:@{} error:nil];
    self.recordFileUrl = url;


    AVAudioUnitReverb * reverd = [[AVAudioUnitReverb alloc] init];
    reverd.wetDryMix = 100;
    [reverd loadFactoryPreset:AVAudioUnitReverbPresetLargeRoom];
    [self.engine attachNode:reverd];

    [self.engine attachNode:_mixer];


    [self.engine connect:self.engine.inputNode to:reverd format:audioFile.processingFormat];
    [self.engine connect:reverd to:_mixer format:audioFile.processingFormat];
    [self.engine connect:_mixer to:self.engine.outputNode format:audioFile.processingFormat];

    [_mixer installTapOnBus:0 bufferSize:4096 format:[_engine.inputNode inputFormatForBus:AVAudioPlayerNodeBufferLoops] block:^(AVAudioPCMBuffer * _Nonnull buffer, AVAudioTime * _Nonnull when) {
        [audioFile writeFromBuffer:buffer error:nil];
        NSLog(@"我錄制到的數(shù)據(jù)是 === %@", buffer);
    }];

    [self.engine startAndReturnError:nil];

總結(jié)

通過如上方法可以完整的實(shí)現(xiàn)清唱功能,但是唱吧清唱使用的是AudioUnit,AudioUnit是iOS中音頻的非常底層的實(shí)現(xiàn),由C語言實(shí)現(xiàn),因?yàn)槌芍谐饲宄膺€有很多非常復(fù)雜的音頻處理功能,所以只有AudioUnit可以滿足,但是對于清唱這個(gè)功能來說,兩種實(shí)現(xiàn)方式達(dá)到了同樣的效果,本文介紹的更加輕量級,不過關(guān)于AudioUnit也正在學(xué)習(xí)過程,后續(xù)會輸出相應(yīng)的文章。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,739評論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,634評論 3 419
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,653評論 0 377
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,063評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,835評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,235評論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,315評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,459評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,000評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,819評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,004評論 1 370
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,560評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,257評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,676評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,937評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,717評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,003評論 2 374

推薦閱讀更多精彩內(nèi)容